我们尝试调整JVM的参数,例如,设置更大空间的堆、修改GC的算法等。尽管效果不错,但这种做法显然是治标不治本。
事实上,在这个时候,我们已经感觉到儿童定位软件使用是解决性能问题的关键。无论是CPU还是GC,都与内存的使用密切相关。降低内存的使用,可以减少GC的频率,最终让CPU把更多的时间用于业务计算。
我们找到了一些降低内存使用的线索。
首先,我们要避免在循环中创建新的对象。例如,在循环中不断地调用StringBuffer(通常占用了较多的内存)的toString方法,每一次这样的调用,都会产生一个新的String对象。
其次,我们希望更多的对象是无状态的。这些无状态的对象应该以单个实例的形式来响应外部的调用,这可以避免创建新对象。
再次,我们要快速释放对象。这样做的好处是,可以把对象保留在年轻代(Nurser-y)内存区,并通过GC的次要收集(Minor Collection)来进行回收。释放对象引用的方式也很简单,通常是在使用完对象之后,把对象引用设为null。更新版的JDK提供了垃圾收集的优化算法,可以更加自动化地释放内存。
最后,我们希望正常的逻辑路径中不要包含Exception的处理。例如,有些逻辑NoSuchMethodException来遍历大量不存在的方法。异常对象的创建会占用栈内存。除了上面提到的线索,我们还发现了一些极不合理的做法,例如:不断地往一个静态的StringBuffer中添加信息;应用程序定制了一个cache却没有任何管理机制;大对象的使用没有节制等。
我们针对儿童定位软件开发的问题给出了对应的解决方案,换句话说,就是避免那些不合理的做法。之后,内存的使用状况明显好转,GC的频率也大大下降了。
那么,这些缺陷是软件设计和实现中无法解决的吗?不。
致远服软认为:http://www.soft8.com.cn/不同的JVM在GC的实现上是有很大差异的。关于GC的原理,读者可以去阅读相关的参考资料。我在这里想强调的是一个重要的经验知识。
对于Java程序来说,内存和GC是性能分析的关键。
我们再来看看大连统计数据报表软件开发的竞争公司。线程竞争不会占用CPU资源,相反,竞争的结果是造成CPU的等待。这同样会对性能造成重大的影响。
Yourkit提供了线程报告。我们可以从儿童定位软件开发报告中看到,哪些线程在工作状态、哪些线程在等待状态、哪些线程在堵塞状态。理论上,这份线程报告也许有助于性能分析,但是实际上,我们只能从中得到一些关于系统性能的整体印象,例如,是否存在过多的线程等待等,却没有发现直接的帮助。