`
jetway
  • 浏览: 473589 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

Hessian序列化不设SerializerFactory性能问题

    博客分类:
  • java
 
阅读更多

Hessian序列化不设SerializerFactory性能问题

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

Java代码  收藏代码
  1. private static final SerializerFactory _serializerFactory = new SerializerFactory();  
  2. ByteArrayOutputStream bout = new ByteArrayOutputStream();  
  3. Hessian2Output h2out = new Hessian2Output(bout);  
  4. h2out.setSerializerFactory(_serializerFactory); // 问题所在  
  5. h2out.writeObject(msg);  
  6. h2out.flush();  
  7. byte[] content = bout.toByteArray();  

新版本代码: 
Java代码  收藏代码
  1. UnsafeByteArrayOutputStream bos = new UnsafeByteArrayOutputStream(1024);  
  2. Hessian2Output h2o = new Hessian2Output(bos);  
  3. h2o.writeObject(connReq);  
  4. h2o.flush();  
  5. byte[] content = bos.toByteArray();  

新代码没有调用h2o.setSerializerFactory(serializerFactory); 
就因为这一句,性能下降10倍。 
我们来看一下Hessian3.2.1的源代码: 
Java代码  收藏代码
  1. public void writeObject(Object object)  
  2.   throws IOException  
  3. {  
  4.   if (object == null) {  
  5.     writeNull();  
  6.     return;  
  7.   }  
  8.   
  9.   Serializer serializer;  
  10.   
  11.   serializer = findSerializerFactory().getSerializer(object.getClass());  
  12.   
  13.   serializer.writeObject(object, this);  
  14. }  
  15.   
  16. public final SerializerFactory findSerializerFactory()  
  17. {  
  18.   SerializerFactory factory = _serializerFactory;  
  19.   
  20.   if (factory == null)  
  21.     _serializerFactory = factory = new SerializerFactory();  
  22.   
  23.   return factory;  
  24. }  

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

每一个Hessian2Output内部都会重新new SerializerFactory(); 
应改为: 
Java代码  收藏代码
  1. private static final SerializerFactory DEFAULT_SERIALIZER_FACTORY =new SerializerFactory();  
  2. if (factory == null)  
  3.       _serializerFactory = factory = DEFAULT_SERIALIZER_FACTORY;  

从这里可以看出是创建SerializerFactory的开销非常大,导致性能下降严重, 
这个应该算是Hessian的BUG,这种线程安全的工厂类,就不应该在设默认值时,每次都new一个。 
大家用Hessian的时候请小心这个问题。 
后续还发现,不设置SerializerFactory,会出现大量线程被阻塞: 
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics