1

我曾经定义一个proto文件,例如

option java_package = "proto.data";
message Data {
    repeated string strs = 1;
    repeated int ints = 2;
}

我从网络收到这个对象的输入流(或字节)。然后,通常情况下,我会做一个解析Data.parserFrom(stream)Data.parserFrom(bytes)获取对象。

这样,我必须在 Data 对象上保留全部内存,而我只需要遍历对象中的所有字符串和整数值。当对象大小很大时,这很糟糕。

这个问题我该怎么办?

4

2 回答 2

1

不幸的是,没有办法只解析 protobuf 的一部分。如果你想确定你已经看到了所有strs所有ints,你必须解析整个消息,因为这些值可以以任何顺序出现,甚至可以交错出现。

如果您只关心内存使用而不关心 CPU 时间,那么理论上您可以使用手写解析器来解析消息并忽略您不关心的字段。您仍然需要进行解析工作,您可以立即丢弃它们,而不是将它们保存在内存中。但是,要做到这一点,您需要研究Protobuf 有线格式并编写自己的解析器。您可以使用 Protobuf 的CodedInputStream类,但仍有很多工作需要手动完成。Protobuf 库确实不是为此而设计的。

如果您愿意考虑使用不同的协议框架,Cap'n Proto在设计上与 Pr​​otobufs 极为相似,但其特点是只能读取您关心的部分消息。Cap'n Proto 不会对您不检查的字段产生任何开销,除了显然接收原始消息字节的带宽和内存。如果您正在从文件中读取,并且您使用内存映射(MappedByteBuffer在 Java 中),那么只有您实际使用的消息部分将从磁盘读取。

(披露:我是大多数 Google Protobufs v2(您可能正在使用的版本)以及 Cap'n Proto 的作者。)

于 2015-03-31T16:14:37.210 回答
0

唔。似乎它可能已经实施但没有充分记录。你测试过吗?

请参阅讨论: https ://groups.google.com/forum/#!topic/protobuf/7vTGDHe0ZyM

另请参阅谷歌 github 中的示例测试代码: https ://github.com/google/protobuf/blob/4644f99d1af4250dec95339be6a13e149787ab33/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto

于 2015-09-04T19:17:19.693 回答