【问题标题】:How does protobuf-net achieve respectable performance?protobuf-net 如何实现可观的性能?
【发布时间】:2010-12-15 21:04:57
【问题描述】:

我想了解为什么Marc Gravell 开发的the protocol buffers solution for .NET 这么快。

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

【问题讨论】:

  • 你试过阅读源代码吗?甚至直接问马克?
  • 我试过了,甚至有一些想法,但如果有人能快速给出答案,那就太好了
  • 我会很高兴地谈论这个几个小时 ;-p 但它必须等到我完成工作......
  • 那就等晚上吧。
  • 你的意思是不是一个真正的问题?对于那些不理解这个问题的人来说,这是非常真实的翻译:“使用了哪些编码技术算法或技术,使 protobuf-net 分配比典型的序列化更快?”这不是一个真正的问题吗?

标签: c# .net reflection protocol-buffers protobuf-net


【解决方案1】:

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

在里面,它试图在与成员交谈时合理地使用反射;它使用Delegate.CreateDelegate 与属性对话,并使用DynamicMethod(和自定义IL)与字段对话(如果可能;它取决于目标框架)。这意味着它总是与 known 委托类型交谈,而不仅仅是 DynamicInvoke(这很慢)。

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

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

事后看来,我认为我在泛型这一点上犯了一个错误;复杂性意味着强制泛型进入系统bent it out of shape in a few places,并积极导致一些主要问题(对于复杂模型)on compact framework

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

最近我设法start spending some time on protobuf-net again,所以希望我能清除我积压的请求等并尽快开始。我还打算让它与模型其他而不是反射一起工作(即单独描述线映射)。


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

我还应该澄清一下,如果您想使用生成的代码,有两个(可选的)代码生成路由; protogen.exe 或 VS add-in,允许从 .proto 文件生成代码。但这不是需要 - 如果您有一个现有的 .proto 文件,或者打算与另一种语言(C++ 等)进行互操作以进行合同优先开发,这主要是有用的。

【讨论】:

    【解决方案2】:

    它的性能非常好!

    您可以看到不同格式之间的全面比较,包括我完成的 protobuf- http://maxondev.com/serialization-performance-comparison-c-net-formats-frameworks-xmldatacontractserializer-xmlserializer-binaryformatter-json-newtonsoft-servicestack-text/

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

    我的帖子中的一项测试-

    【讨论】:

    • 问题是性能是如何完成的,而不是性能如何。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多