技术头条 - 一个快速在微博传播文章的方式     搜索本站
您现在的位置首页 --> 算法 --> 解开 phprpc 序列化性能高于 hessian 的秘密

解开 phprpc 序列化性能高于 hessian 的秘密

浏览:3938次  出处信息

    Phprpc, 是一个声称在某些场景下, 性能比hessian还要高的协议.

    下面url是 javaeye andot 写的两个协议的性能测试报告:

    http://www.javaeye.com/topic/333720

    看到这个报告是有点激动的, 那么它到底在实现上有何高明之处呢?

    在这篇文章里, 我会给大家简单阐述一下, 为什么phprpc在某些场景下, 性能会优于hessian.

    首先, 序列化的本意是, 将不同类型的对象转换成统一的字节流, 便于存储和传输.

    Java在早期1.1版时, 就引入 Serializable 接口, 来支持java对象的序列化(通过ObjectInput/OutputStream写入读取).

    但由于实现上过于通用和复杂, 导致其性能下降得比较厉害.

    Hessian的效率高, 主要体现在针对不同类型的转换逻辑上, 做了大量优化(比如数组, 复合对象, 日期类型等)和协议更轻量级..

    那要比hessian性能还高, 要么就是转换逻辑, 比hessian更简单, 要么就是协议更精简, 代码优化的更好.

    当然猜测是没有用的, 下面, 是我读了源码后, 对比得到的结论:

    1, 抛弃OO设计带来的性能提升.

Hessian:

    不同类型的序列化/反序列化都实现了Serializer和Deserializer接口, 然后由 SerializerFactory 根据不同类型(Class)来创建不同的 Serializer / Deserializer.

    内部实现上, 也做了大量的OO抽象设计.这样做的好处就不用多说了.

    上一张hessian序列化实现的类图(部分):

    capture1

Phprpc:

    一个类里实现所有的序列化逻辑, 通过大量的ifelse来做不同类型的判断, 然后通过私有方法来对冗长的转换逻辑做抽象.

    capture2

    结论:

    PHPRPC实例化对象的机会比较少(new对象开销很大), 且代码结构上设计相对精简, 所以, 性能对比hessian有大幅提升.

    2, cache重复对象带来的性能提升.

    比如 String[] str = {“aa”, “bb”, “aa”}; 可以看到 “aa” 字符串出现了两次.

    cache重复对象, 只写入对象的位置引用. 比如上面的例子里, 只往字节流里, 写入了 “aa”和“bb”两个串, 第二个”aa”换成写入位置引用, 反序列化时, 第二个”aa”是直接引用的第一个”aa”.

Hessian:

    在hessian里, byte, char数组及基础类型是不做cache的, 其他类型都做cache.

Phprpc:

    对 byte, char数组也做了cache, 其他跟hessian一样.

    Phprpc Cache重复对象的实现:

    开辟一块单独的cache(序列化结束时, cache会被收回), 用来保存对象的hashcode与对象的关系, 接下来每个对象做序列化前, 会根据自身的hashcode到cache里看看是否已存在, 如果存在, 只写入该对象的位置引用, 否则, 写入对象.

    结论:

    Phprpc测试报告里, “2000次对10000个元素的字节数组”为什么比hessian快, 原因之一就是因为自身对byte数组也做了cache.

    总的来说phprpc在这点上比hessian应该有少量提升.

    总结

    1, 通过优化代码后的phprpc, 确实在某些场景下, 性能要略微高于hessian.

    2, Phprpc在某些场景下, 性能不一定好于hessian.

    比如特殊类型优化, 像

    Class, Javabean, Calendar, Enumeration, InputStream, Iterator, Locale, SqlDate等.

     这些对象都是有特殊含义的, 如果不做特殊处理, 像phprpc那样, 直接把这些对象内部无用的field结构都做序列化, 反而性能会更差.

    3, phprpc的社区现在没hessian成熟, 所以我的观点是优选hessian, 除非你的系统要追求极致, 那个时候, 才考虑phprpc.

    PS: 参考phprpc和hessian, 然后实现Externalizable接口, 可以自己实现某些对象的序列化, 不过有侵入性.

建议继续学习:

  1. 对protostuff和java序列化的小测试    (阅读:3629)
  2. PHP 序列化与 .NET 中其它方式序列化的效率对比    (阅读:2530)
  3. C 语言的数据序列化    (阅读:2320)
  4. 序列化格式YAML初探    (阅读:2065)
  5. Spring的RMI , Http Invoker, Hessian测试结果    (阅读:1862)
  6. String的序列化小结    (阅读:1755)
  7. JAVA序列化和反序列化及漏洞补救    (阅读:896)
QQ技术交流群:445447336,欢迎加入!
扫一扫订阅我的微信号:IT技术博客大学习
© 2009 - 2024 by blogread.cn 微博:@IT技术博客大学习

京ICP备15002552号-1