我曾经定义过一个proto
文件,例如
option java_package = "proto.data";
message Data {
repeated string strs = 1;
repeated int ints = 2;
}
我从网络收到了这个对象的输入流(或字节)。然后,通常我会进行Data.parserFrom(stream)
或Data.parserFrom(bytes)
之类的解析来获取对象。
通过这个,我必须在Data对象上保留完整的内存,而我只需要旅行 对象中的所有字符串和整数值。当对象大小很大时,它会很糟糕。
我应该为这个问题做些什么?
答案 0 :(得分:1)
不幸的是,没有办法解析protobuf的一部分。如果您想确定已经看到strs
的{{1}}或所有的全部,则必须解析整个邮件,因为这些值可以按任何顺序出现,甚至可以交错出现。
如果您只关心内存使用而不关心CPU时间,那么理论上您可以使用手写解析器来解析消息并忽略您不关心的字段。您仍然需要进行解析工作,您可以立即丢弃它们而不是将它们保存在内存中。但是,为此,您需要学习Protobuf wire format并编写自己的解析器。您可以使用Protobuf的ints
类,但仍需要手动完成大量工作。 Protobuf库真的不是为此设计的。
如果您愿意考虑使用不同的协议框架,Cap'n Proto在设计上与Protobufs非常相似,但功能只能读取您关注的部分消息。除了接收原始消息字节的带宽和内存之外,Cap'n Proto不会对您未检查的字段产生任何开销。如果您正在读取文件,并且使用内存映射(Java中为CodedInputStream
),则只会从磁盘中读取您实际使用的消息部分。
(披露:我是大多数Google Protobufs v2(您可能正在使用的版本)以及Cap'n Proto的作者。)
答案 1 :(得分:0)
嗯。它似乎已经实施但没有充分记录。 你测试过吗?
参见讨论: https://groups.google.com/forum/#!topic/protobuf/7vTGDHe0ZyM
另请参阅google的github中的示例测试代码: https://github.com/google/protobuf/blob/4644f99d1af4250dec95339be6a13e149787ab33/java/src/test/java/com/google/protobuf/lazy_fields_lite.proto