[Home]   [TOC]

Blog_XStreamNonStaticInstancePerformanceAnalysis  
XStream非静态化实例的性能问题分析
Updated Mar 6, 2015 by jht5...@gmail.com

XStream非静态化实例的性能问题分析

我们程序中有每次都new 一个JaxbXstreamWrapper实例:

    public String getXmlString() {

        JaxbXstreamWrapper jx = new JaxbXstreamWrapper();
        return jx.getFromObject(this);
    }

实现这货就是XStream的包装!

通过简单的循环测试,我们可以看到FGC的变化:

这个GC的效果相当明显。

通过“classmexer.jar”计算该实例大小,第一次计算出来是“1,163,232”,好家伙这个足足有1M多,这个初始始化当然慢啦!但每次实例化都要1M多么?显然不是,那么每次实例化会有多大呢?

我们知道在JVM中默认的hashCode函数返回的是对象的地址,从java.lang.Object的这个描述可以看到“(This is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the JavaTM programming language.)”,那么对于重载过hashCode方法的类似如何得到这个地址呢?虽然我们知道在C#中这个是可以做到的,但在Java中这个有点困难,但Java提供了另外一个方法,就是“System中的 public static native int identityHashCode(Object x)”。

OK,现在修改classmexer的实现,通过对象的地址来判断是不是同一个对象:

private static Set<Integer> CACULATED_OBJECTS = new HashSet<Integer>();
if (!CACULATED_OBJECTS.contains(addr)) {
    CACULATED_OBJECTS.add(addr);
    long sz = instrumentation.getObjectSize(o); // 只计算未计算过大小的对象的大小
    total += sz;
}

计算多次后得到:

1,163,232
41,832
11,776
11,776
11,776

根据这个结果我们可以判断每次new Xstream会增加11K左右的内存。

但其实我们知道XStream是线程安全的,所以jx对象只要变成static成员就OK了。

这时候再次对40万数据进行测试,发现只要5秒左右就结束了,根本没等我来的及打印GC信息。