gpt4 book ai didi

c# - 关于 c# struct 内存/序列化开销

转载 作者:太空狗 更新时间:2023-10-29 20:00:32 26 4
gpt4 key购买 nike

我的代码是这样的:

[Serializable]
[StructLayout(LayoutKind.Sequential,Pack=1)]
struct Foo
{
public byte Bar;
public Foo(byte b){Bar=b;}
}
public static void Main (string[] args)
{
Foo[] arr = new Foo[1000];
for (int i = 0; i < 1000; i++) {
arr[i]=new Foo(42);
}
var fmt = new BinaryFormatter();
using(FileStream f= File.Create("test.bin")){
fmt.Serialize(f,arr);
}
Console.WriteLine (new FileInfo("test.bin").Length);
}

结果bin文件有10095字节大。为什么我的 Foo 结构会吃掉这么多字节?每个结构体开销的 9 个字节是什么意思?

附言: 我正在为汉字编写一个查找库(它是关于大约 70,000 个字符的信息),db4o 或其他可嵌入的数据库(如 sqlite)有点膨胀。我想以纯字符串格式存储所有信息,这对内存最友好,但不太灵活。我想将信息保存在列表中并将它们作为二进制序列化存储到存档中,我选择了 DotNetZip 进行存档。但是序列化开销是一个意想不到的障碍。一个更好的序列化解决方案会很好,否则我必须以纯字符串格式保存信息并通过硬编码解析它。

最佳答案

并不是 Foo 结构如此“大”,而是您观察到的是二进制序列化格式本身的开销。这个格式包含了一个header,描述对象图的信息,描述array的信息,描述type和assembly信息的strings等等。也就是说它包含了足够的信息让BinaryFormatter.Deserialize给出正如您所期望的那样,您支持一个 Foo 数组。

有关详细信息,这里是详细描述格式的规范:http://msdn.microsoft.com/en-us/library/cc236844(PROT.10).aspx

根据您更新的问题进行编辑:

如果您只想将结构的内容写入流,这可以在不安全的上下文中轻松实现(此代码基于您的示例)。

使用一个小数组写出每个 Foo:

unsafe 
{
byte[] data = new byte[sizeof(Foo)];

fixed (Foo* ptr = arr)
{
for (int i = 0; i < arr.Length; ++i)
{
Marshal.Copy((IntPtr)ptr + i, data, 0, data.Length);
f.Write(data, 0, data.Length);
}
}
}

或者使用一个足够大的数组来写出所有的 Foos:

unsafe 
{
byte[] data = new byte[sizeof(Foo) * arr.Length];

fixed (Foo* ptr = arr)
{
Marshal.Copy((IntPtr)ptr, data, 0, data.Length);
f.Write(data, 0, data.Length);
}
}

根据您的示例,这将写出 1000 个字节,每个字节的值为 42。

但是,这种方法有一些缺点。如果您熟悉用 C 等语言编写结构,那么其中一些应该是显而易见的:

  • 如果您在一台与您用来写入数据的字节序不同的机器上读取数据,您将无法获得所需的结果。您需要定义预期的字节顺序并自行处理与此顺序之间的转换。
  • Foo 不能包含引用类型的字段。这意味着您需要使用长度字段 + char 的固定大小缓冲区而不是 System.String;这可能是一个真正的痛苦。
  • 如果 Foo 包含指针类型或 IntPtr/UIntPtr,则结构的大小可能因机器架构而异。如果可能,您会希望避免使用这些类型。
  • 您需要应用自己的版本控制方案,以便您可以在一定程度上确信读回的数据与预期的结构定义相匹配。对结构布局的任何更改都需要新的版本控制。

BinaryFormatter 为您解决了这些问题,但会产生您在这样做时观察到的空间开销。它旨在以安全的方式在机器之间交换数据。如果您不想使用 BinaryFormatter,那么您需要定义自己的文件格式并自行处理这种格式的读写,或者使用最适合您需要的第三方序列化库(我会将此类库的研究留给您)。

关于c# - 关于 c# struct 内存/序列化开销,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5209297/

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