使用 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<T>
或 IEnumerable<T>
。除非有 LINQ 提供程序可以在您的 .bin 文件中提供 IQueryable<T>
接口,否则您必须:
IEnumerable<T>
编写可以提供IQueryable<T>
的 LINQ 提供程序(如果您的文件很大,这可能是唯一实用的选择),可以在不加载整个文件的情况下处理文件。
【讨论】:
很好,DeserializeItems 提供了一个IEnumerable<T>
API,那么
@Marc:看起来是这样!我曾假设反序列化会将整个文件加载到内存中。显然我错了。
它会懒惰地从流中假脱机 (yield return
) - 非常适合处理大量数据【参考方案4】:
protobuf 可以将文件内容作为流IEnumerable<T>
提供给您,因此您可以轻松做到这一点。不幸的是,我不知道该方法是如何调用的,但在文档中很容易找到。
【讨论】:
@Marc 我应该如何序列化项目以使用 DeserializeItems?你有一个简单的例子吗?我一直试图在 V2 中做到这一点。以上是关于使用 protobuf-net 进行质量过滤的主要内容,如果未能解决你的问题,请参考以下文章
我可以重复使用对象实例来避免使用 protobuf-net 进行分配吗?