Java 应用性能优化是一个老生常谈的话题,典型的性能问题如页面响应慢、接口超时,服务器负载高、并发数低,数据库频繁死锁等。尤为是在“糙快猛”的互联网开发模式大行其道的今天,随着系统访问量的日益增长和代码的臃肿,各类性能问题开始纷至沓来。html
Java 应用性能的瓶颈点很是多,好比磁盘、内存、网络 I/O 等系统因素,Java 应用代码,JVM GC,数据库,缓存等。java
笔者根据我的经验,将 Java 性能优化分为 4 个层级:应用层、数据库层、框架层、JVM 层,如图 1 所示。ios
每层优化难度逐级增长,涉及的知识和解决的问题也会不一样。数据库
好比应用层须要理解代码逻辑,经过 Java 线程栈定位有问题代码行等;缓存
数据库层面须要分析 SQL、定位死锁等;性能优化
框架层须要懂源代码,理解框架机制;服务器
JVM 层须要对 GC 的类型和工做机制有深刻了解,对各类 JVM 参数做用了然于胸。网络
围绕 Java 性能优化,有两种最基本的分析方法:现场分析法和过后分析法。并发
现场分析法经过保留现场,再采用诊断工具分析定位。现场分析对线上影响较大,部分场景(特别是涉及到用户关键的在线业务时)不太合适。app
过后分析法须要尽量多收集现场数据,而后当即恢复服务,同时针对收集的现场数据进行过后分析和复现。下面咱们从性能诊断工具出发,分享搜狗商业平台在其中的一些案例与实践。
性能诊断一种是针对已经肯定有性能问题的系统和代码进行诊断,还有一种是对预上线系统提早性能测试,肯定性能是否符合上线要求。本文主要针对前者,后者能够用各类性能压测工具(例如 JMeter)进行测试,不在本文讨论范围内。
针对 Java 应用,性能诊断工具主要分为两层:OS 层面和 Java 应用层面(包括应用代码诊断和 GC 诊断)。
OS 的诊断主要关注的是 CPU、Memory、I/O 三个方面。
CPU 诊断
对于 CPU 主要关注平均负载(Load Average),CPU 使用率,上下文切换次数(Context Switch)。
经过 top 命令能够查看系统平均负载和 CPU 使用率,图 2 为经过 top 命令查看某系统的状态。
平均负载有三个数字:63.66,58.39,57.18,分别表示过去 1 分钟、5 分钟、15 分钟机器的负载。按照经验,若数值小于 0.7*CPU 个数,则系统工做正常;若超过这个值,甚至达到 CPU 核数的四五倍,则系统的负载就明显偏高。图 2 中 15 分钟负载已经高达 57.18,1 分钟负载是 63.66(系统为 16 核),说明系统出现负载问题,且存在进一步升高趋势,须要定位具体缘由了。
经过 vmstat 命令能够查看 CPU 的上下文切换次数,如图 3 所示:
上下文切换次数发生的场景主要有以下几种:
1)时间片用完,CPU 正常调度下一个任务;
2)被其它优先级更高的任务抢占;
3)执行任务碰到 I/O 阻塞,挂起当前任务,切换到下一个任务;
4)用户代码主动挂起当前任务让出 CPU;
5)多任务抢占资源,因为没有抢到被挂起;
6)硬件中断。
Java 线程上下文切换主要来自共享资源的竞争。通常单个对象加锁不多成为系统瓶颈,除非锁粒度过大。但在一个访问频度高,对多个对象连续加锁的代码块中就可能出现大量上下文切换,成为系统瓶颈。好比在咱们系统中就曾出现 log4j 1.x 在较大并发下大量打印日志,出现频繁上下文切换,大量线程阻塞,致使系统吞吐量大降的状况,其相关代码如清单 1 所示,升级到 log4j 2.x 才解决这个问题。
1 for(Category c = this; c != null; c=c.parent) { 2 // Protected against simultaneous call to addAppender, removeAppender,… 3 synchronized(c) { 4 if (c.aai != null) { 5 write += c.aai.appendLoopAppenders(event); 6 } 7 … 8 } 9 }
Memory
从操做系统角度,内存关注应用进程是否足够,可使用 free –m 命令查看内存的使用状况。经过 top 命令能够查看进程使用的虚拟内存 VIRT 和物理内存 RES,根据公式 VIRT = SWAP + RES 能够推算出具体应用使用的交换分区(Swap)状况,使用交换分区过大会影响 Java 应用性能,能够将 swappiness 值调到尽量小。由于对于 Java 应用来讲,占用太多交换分区可能会影响性能,毕竟磁盘性能比内存慢太多。
I/O
I/O 包括磁盘 I/O 和网络 I/O,通常状况下磁盘更容易出现 I/O 瓶颈。经过 iostat 能够查看磁盘的读写状况,经过 CPU 的 I/O wait 能够看出磁盘 I/O 是否正常。若是磁盘 I/O 一直处于很高的状态,说明磁盘太慢或故障,成为了性能瓶颈,须要进行应用优化或者磁盘更换。
除了经常使用的 top、 ps、vmstat、iostat 等命令,还有其余 Linux 工具能够诊断系统问题,如 mpstat、tcpdump、netstat、pidstat、sar 等。Brendan 总结列出了 Linux 不一样设备类型的性能诊断工具,如图 4 所示,可供参考。
....
转载:https://www.ibm.com/developerworks/cn/java/j-lo-performance-tuning-practice/index.html