我只是简单的对象结构中只包含结构体的地理数据,我的所有字段都是有价值的类型.
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; }
父母[] – 的小部分数据很好地被分块.每个数组包含几千个父实例.我有太多的数据保留所有的内存,所以我需要交换这些块到磁盘来回. (一个文件将产生约2-300KB).
将Parent []序列化/反序列化到dumpint到磁盘的一个字节[]并读回来是最有效的方式?关于速度,我特别对快速反序列化感兴趣,写速度并不那么关键.
简单的BinarySerializer会好吗?
还是应该用StructLayout
(see accepted answer)?我不知道这是否适用于Parent.children的数组字段.
更新:对注释的响应 – 是的,对象是不可变的(代码更新),实际上,子字段不是值类型. 300KB的声音听起来不多,但是我有这样的数十万个文件,所以速度很重要.
解决方法
BinarySerializer是一个非常通用的串行器.它不会像自定义实现一样执行.
幸运的是,您的数据仅由结构体组成.这意味着您将能够修复Child的structlayout,只需使用从磁盘读取的字节[],使用不安全的代码对子数组进行位复制.
对于父母来说,这不是那么容易,因为你需要分开对待孩子.我建议您使用不安全的代码从您读取的字节[]中复制可复制的字段,并单独反序列化子对象.
您是否考虑使用内存映射文件将所有子项映射到内存?然后,您可以重新使用操作系统缓存设施,而不是处理读取和写入.
零拷贝反序列化一个孩子[]看起来像这样:
byte[] bytes = GetFromDisk(); fixed (byte* bytePtr = bytes) { Child* childPtr = (Child*)bytePtr; //now treat the childPtr as an array: var x123 = childPtr[123].X; //if we need a real array that can be passed around,we need to copy: var childArray = new Child[GetLengthOfDeserializedData()]; for (i = [0..length]) { childArray[i] = childPtr[i]; } }