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

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序列化实现的类图(部分):

phprpc类图结构

Phprpc:

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

代码片段:

phprpc 代码逻辑片段

结论:

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接口, 可以自己实现某些对象的序列化, 不过有侵入性.

作者:Ken Wu 原文链接:http://kenwublog.com/explore-phprpc-secret-of-serialization-performance

2009/03/15 | Posted in Development Skills
  1. Jack(leimeng)
    2009/06/01 09:09 | #1

    恭喜开博~

  2. dealstar
    2009/06/01 09:23 | #2

    写得不错!

  3. 2009/06/01 09:25 | #4

    对了, 忘记写开播首文了.

Leave a comment

Attention: Java syntax highlighting is enable. For example: <pre lang="java"> class A {} </pre>