Hessian序列化不设SerializerFactory性能有关问题
Hessian序列化不设SerializerFactory性能问题Hessian序列化不设SerializerFactory性能问题服务框架全面重
Hessian序列化不设SerializerFactory性能问题
Hessian序列化不设SerializerFactory性能问题
服务框架全面重构后,因换了通讯协议,采用Magic头识别新旧版本,?
性能测试发现,在兼容旧版本模式下,性能下降10倍,?
原来一个1ms到2ms的请求,现在需要11ms到12ms,?
对比新旧版本代码,发现四个不同点:?
(1)UnsafeByteArrayOutputStream是不是比ByteArrayOutputStream慢很多??
(2)通过java.nio.ByteBuffer转换到mina的ByteBuffer映射写入慢很多??
(3)重复使用一个ByteArrayOutputStream是不是比多个ByteArrayOutputStream慢很多??
(4)没有设置SerializerFactory会比设置了慢很多??
逐个验证,前面三个对性能几乎没有影响,修改第四个,性能立马提升。?
旧版本代码:?
Java代码??

- private?static?final?SerializerFactory?_serializerFactory?=?new?SerializerFactory();??
- ByteArrayOutputStream?bout?=?new?ByteArrayOutputStream();??
- Hessian2Output?h2out?=?new?Hessian2Output(bout);??
- h2out.setSerializerFactory(_serializerFactory);?//?问题所在??
- h2out.writeObject(msg);??
- h2out.flush();??
- byte[]?content?=?bout.toByteArray();??
新版本代码:?
Java代码??

- UnsafeByteArrayOutputStream?bos?=?new?UnsafeByteArrayOutputStream(1024);??
- Hessian2Output?h2o?=?new?Hessian2Output(bos);??
- h2o.writeObject(connReq);??
- h2o.flush();??
- byte[]?content?=?bos.toByteArray();??
新代码没有调用h2o.setSerializerFactory(serializerFactory);?
就因为这一句,性能下降10倍。?
我们来看一下Hessian3.2.1的源代码:?
Java代码??

- public?void?writeObject(Object?object)??
- ??throws?IOException??
- {??
- ??if?(object?==?null)?{??
- ????writeNull();??
- ????return;??
- ??}??
- ??
- ??Serializer?serializer;??
- ??
- ??serializer?=?findSerializerFactory().getSerializer(object.getClass());??
- ??
- ??serializer.writeObject(object,?this);??
- }??
- ??
- public?final?SerializerFactory?findSerializerFactory()??
- {??
- ??SerializerFactory?factory?=?_serializerFactory;??
- ??
- ??if?(factory?==?null)??
- ????_serializerFactory?=?factory?=?new?SerializerFactory();??
- ??
- ??return?factory;??
- }??
看代码,在writeObject()时,如果发现没有设置SerializerFactory,会自动设一个SerializerFactory,?
看起来好像没有问题,我们自己设的SerializerFactory也是直接new出来的,没做什么手脚,?
那为什么性能会下降这么快呢?开始还真被这行代码唬住了,看起来没啥区别,?
仔细一想,才发现,Hessian2Output对象是prototype的,?
每次请求,都会创建一个实例,用完即销毁,这样的话,基于下面的方式:?
Java代码??

- if?(factory?==?null)??
- ??????_serializerFactory?=?factory?=?new?SerializerFactory();?//?问题所在??
每一个Hessian2Output内部都会重新new SerializerFactory();?
应改为:?
Java代码??

- private?static?final?SerializerFactory?DEFAULT_SERIALIZER_FACTORY?=new?SerializerFactory();??
- if?(factory?==?null)??
- ??????_serializerFactory?=?factory?=?DEFAULT_SERIALIZER_FACTORY;??
从这里可以看出是创建SerializerFactory的开销非常大,导致性能下降严重,?
这个应该算是Hessian的BUG,这种线程安全的工厂类,就不应该在设默认值时,每次都new一个。?
大家用Hessian的时候请小心这个问题。?
后续还发现,不设置SerializerFactory,会出现大量线程被阻塞:?