我有一个解决方案,我需要非常快速地将对象读入内存,但是二进制流可能会缓存在内存中压缩以节省磁盘 io 上的时间。

我尝试了不同的解决方案,显然 XmlTextWriter 和 XmlTextReader 不是那么好,内置的二进制序列化也不是。 Protobuf-net 非常好,但仍然有点太慢。以下是一些统计数据:

文件大小 XML:217 kb

文件大小二进制:87 kb

压缩二进制:26 KB

压缩的 XML:26 KB

使用 XML (XmlTextReader) 反序列化:8.4 sek

用二进制反序列化 (Protobuf-net):6.2 秒

使用 Binary wo string.interning (Protobuf-net) 反序列化:5.2 sek

从内存中使用二进制反序列化:5.9 Sek

将二进制文件解压到内存中的时间:1.8 秒

使用 Xml (XmlTextWriter) 序列化:11 秒

用二进制序列化(Protobuf):4 秒

使用二进制长度前缀序列化(Protobuf-net):3.8 秒

这让我思考,似乎(如果我错了请纠正我)反序列化的主要罪魁祸首是实际的字节转换而不是 IO。如果是这种情况,那么它应该是使用新的 Parallel 扩展的候选者。

由于我在二进制 IO 方面有点新手,但在我投入时间解决问题之前,我会很感激一些输入:)

为简单起见,假设我们想要反序列化一个没有可选字段的对象列表。我的第一个想法是简单地用长度前缀存储每个。将每个的 byte[] 读入 byte[] 的列表,并使用 PLINQ 进行 byte[] -> 对象反序列化。

然而,使用这种方法我仍然需要单线程读取字节 [],所以也许可以将整个二进制流读入内存(顺便说一句,多大的二进制文件是可行的?)并在二进制文件的开头存储如何有许多对象,每个对象的长度和偏移量。然后我应该能够只创建 ArraySegments 或其他东西,并且也可以并行地进行分块。

那么大家觉得怎么样,可行吗?

最佳答案

我经常做这样的事情,没有什么比使用 BinaryReader 读取内容更胜一筹了。据我所知,没有比使用 BinaryReader.ReadInt32 读取 32 位整数更快的方法了。

您可能还会发现使其并行并重新连接在一起的开销太大。如果你真的想走并行路线,我会建议使用多个线程来读取多个文件,而不是多个线程来读取多个块中的一个文件。

您还可以调整块大小以使其与磁盘块大小匹配,但是在您的应用程序和磁盘之间存在很多抽象级别,这可能会浪费时间。

关于c# - 并行二进制反序列化?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1935109/

10-11 22:10
查看更多