protobuf-net 如何实现可观的性能?

发布于 2024-08-11 03:54:20 字数 344 浏览 8 评论 0原文

我想了解为什么 针对 .NET 的协议缓冲区解决方案Marc Gravell 速度很快。

我可以理解最初的 Google 解决方案是如何实现其性能的:它预先生成了对象序列化的优化代码;我已经手工编写了一些序列化,并且知道如果避免反射,可以通过这种方式编写相当快的代码。但 Marc 的库是一个运行时解决方案,它使用属性并且不生成任何生成的代码。那么它是如何运作的呢?

I want to understand why the protocol buffers solution for .NET developed by Marc Gravell is as fast as it is.

I can understand how the original Google solution achieved its performance: it pre-generates optimized code for object serialization; I've written some serialization by hand and know that it is possible to write pretty fast code this way if you avoid reflection. But Marc's library is a runtime solution that uses attributes and doesn't produce any generated code. So how does it work ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

迟到的我 2024-08-18 03:54:20

protobuf-net使用策略模式;根据需要(每种类型仅一次),它使用反射来查看类型,并构建一组序列化器(基于通用接口),可用于序列化和反序列化 - 所以在使用时它只是单步执行已知的序列化器集。

其中,它试图在与成员交谈时合理地利用反思;它使用 Delegate.CreateDelegate 与属性对话,并使用 DynamicMethod (和自定义 IL)与字段对话(如果可能的话;这取决于目标框架)。这意味着它始终与已知委托类型通信,而不仅仅是DynamicInvoke(这非常慢)。

不用发疯,代码确实在以下方面进行了一些优化(可以说以牺牲可读性为代价):

  • )本地byte[]缓冲(输入/输出流)
  • 使用固定大小的数组(而不是使用固定大小的数组 列表等);也许太多地
  • 使用泛型来避免
  • 围绕二进制处理循环进行大量调整/旋转/等等

事后看来,我认为我在泛型点上犯了一个错误;复杂性意味着强制仿制药进入系统将其从在一些地方塑造,并主动导致一些重大问题(对于复杂模型)紧凑框架

我有一些设计(仅在我的脑海中)使用通用接口来重构它,并改为(对于合适的框架)更多地使用ILGenerator(我的第一选择应该是Expression,但这会强制使用更高的框架版本)。然而,问题是这需要相当长的时间才能开始工作,直到最近 我已经被淹没了

最近,我成功再次开始在 protobuf-net 上花费一些时间,所以希望我能清除积压的请求等并尽快开始处理。我还打算让它与反射之外的模型一起使用(即单独描述接线映射)。


并且不会生成任何生成的代码

我还应该澄清,如果您想使用生成的代码,有两个(可选)代码生成路径; protogen.exe,或 VS 加载项< /a>,允许从 .proto 文件生成代码。但这并不是需要 - 它主要在您有现有的 .proto 文件或打算与另一种语言(C++ 等)互操作以进行合约优先开发时有用。

protobuf-net uses a strategy pattern; as needed (once only per type) it uses reflection to look at the types, and builds a set of serializers (based on a common interface) that it can use to serialize and deserialize - so when in use it is just stepping through the known set of serializers.

Inside that, it tries to make sensible use of reflection when talking to members; it uses Delegate.CreateDelegate to talk to properties, and DynamicMethod (and custom IL) to talk to fields (when possible; it depends on the target framework). This means that it is always talking to known delegate types, rather than just DynamicInvoke (which is very slow).

Without going mad, the code does have some optimisations (arguably at the expense of readability) in terms of:

  • local byte[] buffering (of the input/output streams)
  • using fixed-size arrays (rather than lists etc); perhaps too much
  • using generics to avoid boxing
  • numerous tweaks/twiddles/etc around the binary processing loops

In hindsight, I think I made a mistake on the generics point; the complexity meant that forcing generics into the system bent it out of shape in a few places, and actively causes some major problems (for complex models) on compact framework.

I have some designs (in my head only) to refactor this using non-generic interfaces, and to instead (for suitable frameworks) make more use of ILGenerator (my first choice would have been Expression, but that forces a higher framework version). The problem, however, is that this is going to take a considerable amount of time to get working, and until very recently I've been pretty swamped.

Recently I've managed to start spending some time on protobuf-net again, so hopefully I'll clear my backlog of requests etc and get started on that soon. It is also my intention to get it working with models other than reflection (i.e. describing the wire mapping separately).


and doesn't produce any generated code

I should also clarify that there are two (optional) codegen routes if you want to use generated code; protogen.exe, or the VS add-in, allow code generation from a .proto file. But this is not needed - it is useful mainly if you have an existing .proto file, or intent to interoperate with another language (C++ etc) for contract-first development.

谁把谁当真 2024-08-18 03:54:20

其性能非常好!

你可以看到我做的包括protobuf在内的不同格式的综合比较——
http ://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

此比较包括大小数据样本和不同格式。

我的帖子中的测试之一
在此处输入图像描述

Its performance very good!

You can see a comprehensive comparison between different formats including protobuf done by me-
http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

This comparison includes large and small data samples and different formats.

One of the tests in my post-
enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文