gpt4 book ai didi

c# - 有没有一种方法可以在 .NET Core 中利用 session 化存储而无需二进制序列化程序的开销?

转载 作者:行者123 更新时间:2023-11-30 22:55:24 24 4
gpt4 key购买 nike

.net 核心应用程序中的 session 存储要求您先将其转换为字节数组,然后再检索它。与 .net 框架存储相比,这些序列化和反序列化操作的开销正在产生大量开销。在我们的 .Net 框架应用程序中需要 5 毫秒的操作在 .Net 核心中需要 850 毫秒以上。我需要能够以高性能方式从服务器缓存存储和检索相当大量的数据,类似于我们在 .Net 框架中使用 session 化存储的方式。

我们的应用程序使用大量有点大的 ADO.NET 数据表。它们包含数千行和数十列的情况并不少见。过去,我们使用带有 session 存储的 .Net 框架来快速从 session 中检索 ADO.NET 数据表对象。

DataTable dt = new DataTable();
HttpContext.Current.Session["data"] = dt; // store in session
dt = (DataTable)HttpContext.Current.Session["data"]; // retrieve from session

我们也有自己的自定义类,这些类以数据表作为成员。这些类以不同的方式处理数据。我们还从 session 中存储和检索它们。

[Serializable]
MyClass {
public DataTable dt;
}

在我们的 .NET 框架应用程序中,典型的过滤和分页数据请求需要大约 5 毫秒的往返时间。 session 访问非常快,每次 get 和 set 操作的性能损失可以忽略不计。

我们一直在尝试过渡到 .NET Core,它管理 session 的方式有点不同。我无法在 session 中存储和检索任何对象,而是首先必须将其转换为字节数组。我正在使用带有一点逻辑的二进制格式化程序来处理获取和设置操作。下面的代码并不像它应该的那样高效,但到目前为止最大的瓶颈是 retrieveData 方法中的反序列化操作。

Public class SessionManager : ISessionManager
{
private readonly IHttpContextAccessor _contextAccessor;
public SessionManager(IHttpContextAccessor contextAccessor) {
_contextAccessor = contextAccessor;
}
public T get<T>(string key)
{
object data = retrieveData(key);
return data == null ? default(T) : (T)data;
}

public void set(string key, object data)
{
serializeBinary(key, data);
}

public void remove(string key) {
_contextAccessor.HttpContext.Session.Remove(key);
}

private void serializeBinary(string key, object data) {
BinaryFormatter bf = new BinaryFormatter();
using (var ms = new MemoryStream())
{
bf.Serialize(ms, data);
var bytes = ms.ToArray();
_contextAccessor.HttpContext.Session.Set(key, bytes);
}
}

private object retrieveData(string key) {
byte[] data = null;
_contextAccessor.HttpContext.Session.TryGetValue(key, out data);
if (data == null) return null;
using (MemoryStream ms = new MemoryStream(data))
{
IFormatter br = new BinaryFormatter();
return br.Deserialize(ms);
}
}
}
}

用法:

MyClass c;
c.dt = _myRepo.getLotsOfData();
_SessionManager.set("data", c);
c = _SessionManager.get<MyClass>("data");

我们在数据表上执行的相同分页和过滤操作,使用相同的类,需要 850 毫秒到 950 毫秒才能完成,而我们的 .Net 框架应用程序需要 5 毫秒。在 visual studio 中分析性能,反序列化操作占用了大部分时间,仅此操作就耗时 600 毫秒。

我知道其他库(如 protobuf)比二进制格式化程序快得多,这可能是我下一步要去的地方。但是,如果我将反序列化时间降低到300ms甚至200ms,相比.Net Framework我还是损失了很多性能。

在我看来,似乎需要一种不同的缓存策略。有没有一种方法可以在 .Net 核心应用程序中存储和检索数据,而不需要首先对数据进行序列化和反序列化的开销?

最佳答案

Our apps consume a lot of somewhat large ADO.NET datatables. It is not uncommon for them to contain thousands of rows and dozens of columns.

我想我们已经找到问题了:)

建议:

  1. 不要尝试在这种状态下序列化庞大的数据集;它们太贵了
  2. BinaryFormatter 中序列化 DataSet 之前启用 dataSet.RemotingFormat = System.Data.SerializationFormat.Binary;
  3. 停止使用DataSet并停止使用BinaryFormatter;我不是随便说的 - 它们非常昂贵,所以如果数据实际上非常固定,请考虑使用具有不同序列化程序的 POCO 类型 - protobuf 会很多 CPU 和带宽(数据量)效率更高

关于c# - 有没有一种方法可以在 .NET Core 中利用 session 化存储而无需二进制序列化程序的开销?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55271866/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com