系统:windows XP
内存:4G
CPU:英特尔 双核 2.66
应用容器:tomcat
数据库:mysql
使用工具:jprofiler,eclipse
目标:寻求影响Gboat2平台启动慢的 最重要 原因,次要的暂不考虑
以下是此次工作内容原因分析及解决过程,并列出解决前后之对比数据。
问题原因:
线程阻塞:借助经jprofiler工具 可以看出,大量的线程发生了阻塞。
被阻塞线程所做的工作:spring-dm会为bundle创建application context.
推测结论:大量的线程被阻塞,断定可能有性能瓶颈点;
具体原因分析如下:
系统存在性能瓶颈点:借助jprofiler(参见附图,最后)和eclipse可以断定:spiring-dm在创建application context.
的过程中存在性能瓶颈点,为:URLHandlersBundleStreamHandler.getHostAddress,即创建application context的线程 在此被阻塞。(附图可以清晰的看出)
深层次原因:
Spring 在创建application context的时候,需要加载一些资源 比如xml,spring 借助OsgiBundleResourcePatternResolver创建 大量的UrlContextResource,并这些对象放到集合中去。就是在往集合中放时产生的问题。
因为:UrlContextResource 这个对象 有自己的hashcode方法,实现具体调用 URL中的hashcode方法,URL中的hashcode方法如下图:
里面的handler在平台环境中即为:URLHandlersBundleStreamHandler,这个类的handlers的hashcode方法为(在其父类URLStreamHandler中):
请看划线部分的方法:这个方法是我们的性能瓶颈点(通过jprofiler和eclipse debug窗口分析出)。
此方法的内容如下:
解决思路:felix官方网站最高版本的此类和目前此类做了对比,发现不同,分析不同后,找到解决我们这个问题方法。
解决问题:在类URLHandlersBundleStreamHandler中复写方法getHostAddress 把同步去掉
返回Null即可。(参照felix 4.0.2)
涉及到此问题的jar包:org.apache.felix.framework-1.4.1.jar,已经对此修改,目前未上传。
解决前后启动前后对比:A,修改前折线;B,修改后折线
图形分析:分界点250个bundles,250个bundle 由图形可以看出,基本差别不大,但超过250个bundle后,可以看出巨大的性能差异。
同样的环境:
300个bundle前后差六倍左右
350个bundle前后差七倍左右
400个bundle前后差八倍左右
450个bundle前后差十一倍左右
500个bundle前后差十四倍左右
。。
。。
。。
具体参照饼状图
折线图:秒/bundles数量
柱状图:解决前测试到500个bundles,解决后测试到1000个bundle
附图:线程阻塞图
线程状态图:
线程实时状态图: