Protocol buffers Google protobuf和大型二进制blob

Protocol buffers Google protobuf和大型二进制blob,protocol-buffers,rpc,Protocol Buffers,Rpc,我正在构建一个软件来远程控制连接到另一台PC的无线电硬件 我计划使用ZeroMQ进行传输,并使用一个类似RPC的请求-应答,其上有表示操作的不同消息 虽然我的大多数消息只是一些控制和状态信息,但应该有一个选项来设置要传输的数据块或请求接收的数据块。这些数据blob通常在5-10MB的范围内,但也可以使用高达几个100MB的较大blob 对于消息格式,我发现googleprotocolbuffers非常吸引人,因为我可以在传输链路上定义一种消息类型,该类型具有所有命令和响应的可选元素。然而,pro

我正在构建一个软件来远程控制连接到另一台PC的无线电硬件

我计划使用ZeroMQ进行传输,并使用一个类似RPC的请求-应答,其上有表示操作的不同消息

虽然我的大多数消息只是一些控制和状态信息,但应该有一个选项来设置要传输的数据块或请求接收的数据块。这些数据blob通常在5-10MB的范围内,但也可以使用高达几个100MB的较大blob

对于消息格式,我发现googleprotocolbuffers非常吸引人,因为我可以在传输链路上定义一种消息类型,该类型具有所有命令和响应的可选元素。然而,protobuf FAQ指出,如此大的消息将对性能产生负面影响


所以问题是,它到底有多糟糕?预计会有什么负面影响?我真的不想把整个通信建立在protobuf的基础上,结果却发现它不起作用。

我没有时间为您做这件事,但我会浏览一下。更好的方法是,继续使用一个大的
字节
字段编写代码,从源代码构建protobuf,并在调试器中逐步执行,以查看在发送和接收大blob时发生的情况

根据经验,我可以告诉您,大型
重复消息
字段的效率不高,除非它们具有
[packed=true]
属性,但这仅适用于基本类型

我的直觉是,大的
字节
字段将是有效的,但这是完全没有根据的

你也可以绕过Protobuf来处理你的大斑点:

message BlobInfo {
    required fixed64 size;
    ...
}

message MainFormat {
    ...
    optional BlobInfo blob;
}
然后,您的解析代码如下所示:

...
if (message.has_blob()) {
    uint64_t size = msg.blob()->size();
    zmqsock.recv(blob_buffer, size);
}

坦率地说,与其说是性能本身,不如说是库的设计方式不适合处理大型消息。例如,您必须一次解析一条消息,然后一次序列化它。因此,如果您有一条包含100MB blob的消息,那么您无法读取消息的任何部分,除非您读取整个100MB并在解析时阻止调用线程。同样有问题的是,100MB的blob将被分配为一个巨大的扁平字节数组。在64位系统上,这可能没问题,但在32位系统上,您可能会遇到地址空间碎片问题。最后,硬消息大小限制为2GB

如果你对这类问题没有意见,那么你几乎可以直接去做。您必须手动覆盖邮件大小限制,出于安全目的,该限制默认为64MB。要做到这一点,您需要在解析来自它的消息之前,手动构造并对其调用
SetTotalBytesLimit()


但就我个人而言,我建议您尝试设计您的系统,使大blob可以分割成小块。

分块是推荐的方法:协议缓冲区非常适合处理大数据集中的单个消息。通常,大型数据集实际上只是一个小数据块的集合,其中每个小数据块可能是一个结构化数据块。尽管协议缓冲区不能一次处理整个集合,但使用协议缓冲区对每个片段进行编码可以大大简化您的问题:现在您只需要处理一组字节字符串,而不是一组结构。-@的确,那篇文章是我写的我想通过协议缓冲区发送图像。它们不是很大,可能是50kb到100kb(最大2MB)。protobuf是一个不合适的工具吗?@speedplane如果你把它们放在一个
字节
类型的字段中就可以了。