gpt4 book ai didi

c# - 结构的快速序列化/反序列化

转载 作者:可可西里 更新时间:2023-11-01 08:37:18 26 4
gpt4 key购买 nike

我有大量地理数据以仅包含结构的简单对象结构表示。我的所有字段都是值类型。

public struct Child
{
readonly float X;
readonly float Y;
readonly int myField;
}

public struct Parent
{
readonly int id;
readonly int field1;
readonly int field2;
readonly Child[] children;
}

数据被很好地分块到 Parent[]-s 的一小部分。每个数组包含几千个 Parent 实例。我有太多数据无法全部保存在内存中,因此我需要将这些 block 来回交换到磁盘。 (一个文件将产生大约 2-300KB)。

Parent[] 序列化/反序列化为 byte[] 以转储到磁盘并回读的最有效方法是什么?关于速度,我对快速反序列化特别感兴趣,写入速度并不是那么关键。

简单的 BinarySerializer 就够了吗?或者我应该破解 StructLayout (see accepted answer) ?我不确定这是否适用于 Parent.children 的数组字段。

更新:对评论的回应 - 是的,对象是不可变的(代码已更新)并且 children 字段确实不是值类型。 300KB 听起来不多,但我有无数这样的文件,所以速度很重要。

最佳答案

如果您不想走编写自己的序列化器路线,您可以使用protobuf.net串行器。这是一个小测试程序的输出:

Using 3000 parents, each with 5 children
BinaryFormatter Serialized in: 00:00:00.1250000
Memory stream 486218 B
BinaryFormatter Deserialized in: 00:00:00.1718750

ProfoBuf Serialized in: 00:00:00.1406250
Memory stream 318247 B
ProfoBuf Deserialized in: 00:00:00.0312500

它应该是不言自明的。这只是一次运行,但相当能说明我看到的速度提升 (3-5 倍)。

要使您的结构可序列化(使用 protobuf.net),只需添加以下属性:

[ProtoContract]
[Serializable]
public struct Child
{
[ProtoMember(1)] public float X;
[ProtoMember(2)] public float Y;
[ProtoMember(3)] public int myField;
}

[ProtoContract]
[Serializable]
public struct Parent
{
[ProtoMember(1)] public int id;
[ProtoMember(2)] public int field1;
[ProtoMember(3)] public int field2;
[ProtoMember(4)] public Child[] children;
}

更新:

实际上,编写自定义序列化程序非常简单,这里是一个简单的实现:

class CustSerializer
{
public void Serialize(Stream stream, Parent[] parents, int childCount)
{
BinaryWriter sw = new BinaryWriter(stream);
foreach (var parent in parents)
{
sw.Write(parent.id);
sw.Write(parent.field1);
sw.Write(parent.field2);

foreach (var child in parent.children)
{
sw.Write(child.myField);
sw.Write(child.X);
sw.Write(child.Y);
}
}
}

public Parent[] Deserialize(Stream stream, int parentCount, int childCount)
{
BinaryReader br = new BinaryReader(stream);
Parent[] parents = new Parent[parentCount];

for (int i = 0; i < parentCount; i++)
{
var parent = new Parent();
parent.id = br.ReadInt32();
parent.field1 = br.ReadInt32();
parent.field2 = br.ReadInt32();
parent.children = new Child[childCount];

for (int j = 0; j < childCount; j++)
{
var child = new Child();
child.myField = br.ReadInt32();
child.X = br.ReadSingle();
child.Y = br.ReadSingle();
parent.children[j] = child;
}

parents[i] = parent;
}
return parents;
}
}

这是在简单速度测试中运行时的输出:

Custom Serialized in: 00:00:00 
Memory stream 216000 B
Custom Deserialized in: 00:00:00.0156250

显然,它的灵 active 不如其他方法,但如果速度真的那么重要,它比 protobuf 方法快大约 2-3 倍。它还生成最小的文件大小,因此写入磁盘应该更快。

关于c# - 结构的快速序列化/反序列化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9944994/

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