2

当前是否可以将 IsPacked=true 用于用户定义的结构?如果没有,那么未来是否有计划?

当我尝试将该属性应用于 ColorBGRA8[] 类型的字段时出现以下异常:System.InvalidOperationException:只有简单的数据类型可以使用打包编码

我的场景如下:我正在编写一个游戏,并且有大量用于各种事物的 blitable 结构,例如颜色、向量、矩阵、顶点、常量缓冲区。它们的内存布局需要在编译时精确定义,以匹配例如来自着色器的常量缓冲区布局(通常在哪里字段?需要在 16 字节边界上对齐)。

我并不是要浪费任何人的时间,但是我找不到有关此特定问题的任何最新信息。

回答后编辑

我目前正在测试一个解决方案,该解决方案对几乎所有内容都使用 protobuf-net,但用户定义的大型数组除外,但可以使用 blitable 结构。我所有的自定义结构数组字段都已替换为可以打包的字节数组。在 protobuf-net 完成数据反序列化后,我通过 p/invoke 使用 memcpy 以便能够再次使用自定义结构数组。

以下数字来自对一个实例进行序列化的测试,该实例包含 byte[] 或 ColorBGRA8[] 的一个字段。原始测试数据约为 38MiB 的数据,例如颜色数组中的 1000000 个条目序列化是使用 MemoryStream 在内存中的一种。

编写
平台.Copy + Protobuf: 51ms, Size: 38,15 MiB
Protobuf: 2093ms, Size: 109,45 MiB

阅读
Platform.Copy + Protobuf:43ms Protobuf:2307ms

测试表明,对于包含或多或少随机数据的庞大数组,可能会出现明显的内存开销。如果不是(反)序列化时间,这不会有什么大不了的。我知道 protobuf-net 可能不是为我的极端情况设计的,更不用说针对它进行优化了,但这是我不愿意接受的。

我想我会坚持使用这种混合方法,因为 protobuf-net 对其他一切都非常有效。

4

1 回答 1

4

简直是“不适用”。引用编码规范

只有原始数字类型(使用 varint、32 位或 64 位连线类型的类型)的重复字段才能被声明为“打包”。

这不适用于自定义结构或类。此处适用的两种方法是字符串(以长度为前缀)和组(开始/结束标记)。后者的编码通常更便宜,但谷歌更喜欢前者。

Protobuf 并非旨在任意匹配某些其他字节布局。它是自己的编码格式,仅用于处理/输出 protobuf 数据。这就像说“我正在编写 XML,但我希望它看起来像 {non-xml}”。

于 2013-04-16T19:16:19.273 回答