谷歌protobuf和大型二进制blob

时间:2014-03-10 18:52:21

标签: protocol-buffers rpc

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

我计划使用ZeroMQ进行传输,并使用类似RPC的请求 - 回复,并在其上面显示代表操作的不同消息。

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

对于消息格式,我发现google协议缓冲区非常吸引人,因为我可以在传输链接上定义一个消息类型,它具有所有命令和响应的可选元素。但是,protobuf常见问题解答表明,如此大的消息会对性能产生负面影响。

所以问题是,它实际上有多糟糕?会有什么负面影响?我真的不想将整个通信基于protobuf,只是为了发现它不起作用。

2 个答案:

答案 0 :(得分:14)

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

如果您对这些问题感到满意,那么您几乎可以做到这一点。您必须手动覆盖邮件大小限制,出于安全考虑,默认为64MB。为此,您需要手动构造CodedInputStream并在解析消息之前调用SetTotalBytesLimit()

但我个人建议你尝试设计你的系统,这样大块的blob就可以分成小块。

答案 1 :(得分:3)

我没有时间为你做这件事,但我会浏览Protobuf source code。更好的是,继续使用大bytes字段编写代码,从源代码构建protobuf,并在调试器中逐步执行,以查看发送和接收大blob时会发生什么。

根据经验,我可以告诉您,大型repeated Message字段有效,除非它们具有[packed=true]属性,但这仅适用于基本类型。

我的直觉是大bytes字段效率很高,但这完全没有根据。

你也可以为你的大blob绕过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);
}