使用 protobuf-net 将打包字节反序列化为 Stream 成员

Deserializing packed bytes to a Stream member with protobuf-net

有没有一种方法可以将 bytes 字段反序列化为 Stream 成员,而无需 protobuf-net 预先分配一个新的(可能是大的)byte[]?

我正在寻找这样的东西:

[ProtoContract]
public class Message
{
    [ProtoMember(1)]
    Stream Payload { get; set; }
}

流可以由预分配的缓冲池支持,例如Microsoft.IO.RecyclableMemoryStream。即使在下降到 ProtoReader 进行反序列化之后,我所看到的只是 AppendBytes,它总是分配一个字段长度的缓冲区。必须进一步下降到 DirectReadBytes,它只直接在消息流上运行——我想避免这种情况。

作为背景,我正在使用 protobuf-net 来 serialize/deserialize 通过网络传输消息。这是一个用于在客户端之间传递消息的中间层组件,因此消息实际上是一个包含二进制负载的信封:

message Envelope {
  required string messageId = 1;
  map<string, string> headers = 2;
  bytes payload = 3;
}

payload 的大小限制为 ~2 MB,但足以让 byte[] 落入 LOH。

使用 Protobuf-net: Serializing a 3rd party class with a Stream data member 中的代理项不起作用,因为它只是包装了相同的整体数组。

Memory usage serializing chunked byte arrays with Protobuf-net 中提到了一种应该有效的技术,将 bytes 更改为 repeated bytes 并依靠发送者来限制每个块。这个解决方案可能足够好,它会阻止 LOH 分配,但它不允许缓冲池。

这里的问题是关于 payload 字段的。不,目前没有一种机制来处理这个问题,但肯定是可以研究选择的东西。可能是我们可以在序列化上下文上执行类似 ArraySegment<byte> AllocateBuffer(int size) 回调的操作,调用者可以使用它来控制分配(这样做的好处是 protobuf-net 实际上不适用于 ArraySegment<byte>,所以这将是一个纯粹的增量更改,不会影响任何现有的工作代码;如果没有提供回调,我们大概会像现在一样分配一个平面缓冲区)。我对其他建议持开放态度,但现在:不 - 它会在内部分配一个 byte[]