.net 从文件中反序列化数据。性能问题

.net 从文件中反序列化数据。性能问题,.net,optimization,performance,serialization,.net,Optimization,Performance,Serialization,我从数据库中读取了一个包含100多万条记录的表。我需要3分钟才能在内存中找到一个填充的对象。我想优化这个过程,并使用二进制BinaryFormatter将这个对象序列化为一个文件。它创建了一个大小为1/2GB的文件。在我将此文件反序列化回内存对象之后。这花了11分钟 问题是:为什么从数据库中读取所有这些数据比从文件中读取要快得多?是否有可能以某种方式优化反序列化过程 数据库在我做这个测试的同一台机器上。此时没有其他进程占用CPU时间。CPU有4个内核和40GB内存 编辑:用于反序列化的代码:

我从数据库中读取了一个包含100多万条记录的表。我需要3分钟才能在内存中找到一个填充的对象。我想优化这个过程,并使用二进制BinaryFormatter将这个对象序列化为一个文件。它创建了一个大小为1/2GB的文件。在我将此文件反序列化回内存对象之后。这花了11分钟

问题是:为什么从数据库中读取所有这些数据比从文件中读取要快得多?是否有可能以某种方式优化反序列化过程

数据库在我做这个测试的同一台机器上。此时没有其他进程占用CPU时间。CPU有4个内核和40GB内存

编辑:用于反序列化的代码:

    using (FileStream fs = new FileStream(filename, FileMode.Open))
    {
        var bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
        var data = (MyType)bf.Deserialize(fs);
        ...
    }

我发现序列化是一个相当大的开销,我希望从文件中反序列化这么多数据比从数据库中查询要花费更长的时间。您还需要从磁盘上的文件读取数据,因此这也会很昂贵。如果您试图缓存数据,最好查看一些内存选项。

我注意到.NET初始化XmlSerializer需要相当长的时间。因此,如果您不重用序列化程序对象,那么这样做应该会显著加快该过程

由于二进制序列化程序的工作方式,它的速度非常慢。它将大量基于反射的元数据注入到二进制文件中。几年前,我对一些相当大的结构运行了一些测试,发现XMLSerializer比二进制序列化器更小、更快。算了吧

在这两种情况下,序列化都是通过反射完成的,这很慢。您可以考虑自己的序列化机制。

我曾经创建了自己的二进制序列化机制(使用文件写入/读取),它的执行速度比XML序列化程序快20倍,后者的执行速度比二进制序列化程序快。它也明显更小


你可能想考虑这样做。

< P>我同意布瑞恩的观点。如果编写自己的持久性逻辑,则可以消除反射调用的开销,并完全控制如何从磁盘加载数据。您必须编写更多的代码,但在这种情况下,这可能是优化的代价。

您是否分析了您的特定场景

注释假定问题是反射,但我现在正在处理一个类似的场景(从文件到对象内存树的反序列化),似乎正在发生的是BinaryFormatter.Deserialize()似乎正在逐个读取字节或小块,以便重新水合对象

以下是我拥有的三个最独特的消费功能:

29%Microsoft.Win32.Win32 Native::ReadFile
22%Microsoft.Win32.Win32 Native::SetFilePointerWin32
12%Microsoft.Win32.Win32 Native::SetFilePointer

我想知道是否有一种方法可以告诉BinaryFormatter按块读取,例如,尝试了BufferedStream和MemoryStream,但没有运气…

这是一个很好的定制序列化类,我正在自己的项目中实现,非常容易使用。我会推荐的


显然比标准格式化程序快4倍,并且易于访问内部结构,这意味着您可以编写自己的.NET4并行改进版。

自从我提出这个问题以来,差不多9年过去了。在.NET二进制序列化程序中没有太多更改,但我找到了另一个库来替换它

它被称为Slim Serializer,是NFX库的一部分。以下是一些链接:

努吉:

性能: 这里是一个300k复杂对象的基准测试,它被序列化为一个大约500MB的文件

Bs  = .NET 4.5 Binary Serializer)
Nfx = Nfx slim serializer

Bs  serialization:   00:00:20.7391613 (606,791,842 bytes)
Nfx serialization:   00:00:06.7498946 (538,040,784 bytes)
Bs  deserialization: 00:03:29.8163338
Nfx deserialization: 00:00:02.7875492

另外,从问题(11分钟)和这个答案(3.5分钟)来看,二进制序列化程序的性能差异。我用更好的硬件解释了这一点,并且在反序列化数据后,.NET版本可能会有所改进。

将不会写入磁盘。很抱歉,这是我回答中的一个输入错误。我的意思是从磁盘读取数据,然后反序列化它。您希望将其存储在磁盘上的文件中,而不是存储在数据库中,这将带来更大的开销。基本上,听起来您应该坚持使用数据库作为数据存储。否则,您可能希望将部分数据缓存在内存中,但不能通过序列化和写入文件来实现。这是二进制序列化,而不是xml序列化。但这可能也与二进制序列化程序有关…您应该发布一些代码。你是如何从文件中读取的?您观察到的性能不佳可能是由于读取1/2 GB文件时的I/O开销造成的。想想你的对象有多大(以字节为单位),你会从该文件中获取多少grap字节进行反序列化。您正在使用或考虑使用缓冲流吗?这是代码,没有什么特别的地方可以让它变慢。。。