使用 protobuf-net 进行质量过滤

Posted

技术标签:

【中文标题】使用 protobuf-net 进行质量过滤【英文标题】:Mass filtering with protobuf-net 【发布时间】:2011-02-14 19:09:07 【问题描述】:

我已经用 protobuf-net 序列化了一个对象列表。

理论上,.bin 文件可以包含数百万个对象。

假设对象属于包含以下内容的类:

public string EventName;

我必须进行查询并创建一个包含与查询匹配的对象的列表。 使用 LINQ 从序列化文件中提取匹配对象的正确方法是什么?

【问题讨论】:

【参考方案1】:

protobuf 格式是项的线性序列;您使用的任何索引等只能单独应用。但是,IEnumerable<T> 可用;你可能会发现:

var item = Serializer.DeserializeItems<YourType>(source)
       .First(item => item.Id == id);

做得很好;这个:

被懒惰地假脱机;每个项目都是单独生成的,因此您不需要过多的内存 短路;如果在起点附近找到该项目,它将立即退出

或者对于多个项目:

var list = Serializer.DeserializeItems<YourType>(source)
    .Where(item => item.Foo == foo);

(如果您想在内存中缓冲匹配项,则在上面的末尾添加一个 ToList,如果您只想以仅转发的方式解析一次,则使用不使用 ToList)

【讨论】:

我觉得这个解决方案不错,但是代码应该能够提取出一些匹配查询的对象。 非常感谢,马克 :)。再次。我应该在 DeserializeItems 方法中作为“标签”的参数传递什么? 我做到了。我应该在 deserializeItems 方法中传递什么标签? @Gilad - Serializer.ListItemTag(实际上只是 1) - 前缀样式为 base-128(但无论如何这是默认值)【参考方案2】:

如果你想在选定的元素列表上添加一些投影,你应该试试我的库,https://github.com/Scooletz/protobuf-linq。它们也可在 NuGet 上使用。 该库大大降低了反序列化的开销。在某些情况下,它可能会下降到原始查询的 50%。

【讨论】:

【参考方案3】:

很遗憾,没有。为了使用 LINQ,您的对象必须实现 IQueryable&lt;T&gt;IEnumerable&lt;T&gt;。除非有 LINQ 提供程序可以在您的 .bin 文件中提供 IQueryable&lt;T&gt; 接口,否则您必须:

将文件反序列化到内存中并使用 LINQ-to-objects IEnumerable&lt;T&gt; 编写可以提供IQueryable&lt;T&gt; 的 LINQ 提供程序(如果您的文件很大,这可能是唯一实用的选择),可以在不加载整个文件的情况下处理文件。

【讨论】:

很好,DeserializeItems 提供了一个IEnumerable&lt;T&gt; API,那么 @Marc:看起来是这样!我曾假设反序列化会将整个文件加载到内存中。显然我错了。 它会懒惰地从流中假脱机 (yield return) - 非常适合处理大量数据【参考方案4】:

protobuf 可以将文件内容作为流IEnumerable&lt;T&gt; 提供给您,因此您可以轻松做到这一点。不幸的是,我不知道该方法是如何调用的,但在文档中很容易找到。

【讨论】:

@Marc 我应该如何序列化项目以使用 DeserializeItems?你有一个简单的例子吗?我一直试图在 V2 中做到这一点。

以上是关于使用 protobuf-net 进行质量过滤的主要内容,如果未能解决你的问题,请参考以下文章

使用 protobuf-net 进行枚举序列化

使用 ProtoBuf-Net 进行两组不同的序列化

我可以重复使用对象实例来避免使用 protobuf-net 进行分配吗?

protobuf-net - 列出支持的类型

尝试使用 protobuf-net 通过 gRPC-Web 进行 Azure AD 身份验证

如何使用 protobuf-net 处理 .proto 文件