【发布时间】:2011-12-04 08:13:58
【问题描述】:
我们正在使用 protobuf-net 对公共协议基于 Google 协议缓冲区的应用程序中的消息进行序列化和反序列化。该库非常出色,涵盖了我们的所有需求,除了这个:我们需要在消息实际序列化之前找出序列化消息的长度(以字节为单位)。
The question 已经在一年半前被问过了,根据 Marc 的说法,唯一的方法是序列化到 MemoryStream 并在之后读取.Length 属性。这在我们的案例中是不可接受的,因为 MemoryStream 在后台分配了一个字节缓冲区,我们必须避免这种情况。
来自同一回复的这句话给了我们希望,毕竟它可能是可能的:
如果您阐明用例是什么,我相信我们可以轻松实现 可用(如果还没有)。
这是我们的用例。我们有大小在几字节到两兆字节之间变化的消息。应用程序预先分配用于套接字操作和序列化/反序列化的字节缓冲区,一旦预热阶段结束,就不能创建额外的缓冲区(提示:避免 GC 和堆碎片)。字节缓冲区本质上是池化的。我们还希望尽可能避免在缓冲区/流之间复制字节。
我们提出了两种可能的策略,它们都需要预先设置消息大小:
- 使用(大)固定大小的字节缓冲区并序列化所有可以放入一个缓冲区的消息;使用
Socket.Send发送缓冲区的内容。我们必须知道下一条消息何时无法放入缓冲区并停止序列化。如果没有消息大小,实现此目的的唯一方法是等待Serialize期间发生异常。 - 使用(小)可变大小字节缓冲区并将每条消息序列化到一个缓冲区中;使用
Socket.Send发送缓冲区的内容。为了从池中检查出大小合适的字节缓冲区,我们需要知道序列化消息有多少字节。
由于协议已经定义(我们无法更改)并且要求消息长度前缀为 Varint32,因此我们不能使用SerializeWithLengthPrefix 方法。
那么是否可以添加一种方法来估计消息大小而无需序列化到流中?如果它不适合库的当前功能集和路线图,但可行,我们有兴趣自己扩展库。如果有的话,我们也在寻找替代方法。
【问题讨论】:
标签: c# protobuf-net