1 调优案例分析
1.1 高性能硬件上的程序部署策略
在高性能硬件上部署程序的两种策略:
- 通过64位JDK来使用大内存
- 使用若干个32位虚拟机建立逻辑集群来利用硬件资源
策略1要考虑的问题:
- 使用大内存的前提是有把握应用程序的FUll GC频率控制的足够低,至少低到不会影响用户使用;而控制FULL GC频率的关键是看应用中绝大多数对象能否符合“朝生夕灭”的规律,即大多数对象的生存时间不应该太长
- 内存回收导致长时间停顿
- 64位JDK性能可能不如32位
- 需要保证程序稳定,因为这种程序一旦发生溢出,转储快照会过于庞大而几乎无法分析
- 程序在64位JDK消耗的内存比32位要大
策略2要考虑的问题:
- 在逻辑集群的环境下,要尽量避免节点竞争全局的资源,比如磁盘竞争,各个节点如果同时访问磁盘,会很容易导致IO异常
- 很难最高效率地使用资源池,比如连接池,因为一般是在各个节点建立独立的连接池,这样可能导致一部分节点满了,另一部分没满
- 各个节点会受到32位的内存限制
- 大量使用本地缓存的应用,在逻辑集群中会造成较大的内存浪费,因为每个逻辑节点都有一份缓存,可以考虑把本地缓存换为集中式缓存
1.2 集群间同步导致的内存溢出
NAKACK文件:JBossCache
经过NAKACK栈用于保障各个包的有效顺序及重发
当网络不良好的时候,会产生大量NAKACK文件的堆积
1.3 堆外内存导致的溢出错误
NIO操作会用到直接内存
- Direct Memory: 可通过-XX:MAXDIrectMemorySIze来调整大小,内存不足时抛出OOM
- 线程堆栈:可通过-Xss来调整大小
- Socket缓存区:每个Socket连接都有Receiver和Send两个缓存区,分别占大小37KB和25KB,连接多的话这块内存占用也比较可观
- JNI代码:JNI使用的内存也在堆外
- 虚拟机和GC
1.4 外部命令导致虚拟机缓慢
例如Runtime.getRuntime().exec()
这种调用方式很消耗资源,它需要
- 克隆一个和当前虚拟机拥有一样环境变量的进程
- 用这个进程去执行命令
- 退出这个进程
2. Eclipse运行速度调优
问题一:永久代溢出
问题分析:JDK1.6没有指定-XX:MaxPermSize=256M
解决方案:指定-XX:MaxPermSize=256M
问题二:类加载时间过长
问题分析:字节码验证需要占用大量时间
解决方案:关闭字节码验证,使用参数-Xverify:none
问题三:编译时间过长
问题分析:JDK1.2以后,虚拟机内设了两个运行时编译器,如果方法被调用的次数达到一定程度,就会被判定为热代码,从而交给JIT编译器及时编译为本低代码,这回消耗程序正常运行的时间,即编译时间
解决方案:使用-Xint
禁止编译器运作,但这也会让给Eclipse启动时间变长
C1编译器
C2编译器
问题四:老年代内存自动扩张
解决方案:将老年代容量固定下来
问题五:Eclipse显式调用System.gc()
解决方案:使用-XX:+DisableExplicitGC
问题六:选择收集器不当
网友评论