本文参考《Java性能优化权威指南》
CPU运行队列
# vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
0 0 0 666884 449796 3518324 0 0 0 9 1 1 1 0 99 0 0
0 0 0 666876 449796 3518324 0 0 0 0 282 626 1 0 99 0 0
0 0 0 666876 449796 3518324 0 0 0 44 330 752 1 0 98 1 0
0 0 0 666876 449796 3518324 0 0 0 0 302 647 0 1 99 0 0
0 0 0 666876 449796 3518324 0 0 0 0 327 689 1 0 99 0 0
每1秒,打印一次
r:运行队列长度
运行队列体现了CPU负载情况,代表线程可以运行但是等待可用CPU资源。一般原则:如果很长一段时间里,运行队列长度都超过虚拟处理器数量1倍,需要关注但不需要立刻采取行动。如果很长时间,超过3~4倍,系统已十分缓慢,需要立刻采取行动。
两种方法,增加CPU从根本上解决问题,另一种方法是优化应用,使用更高效的算法降低CPU使用率。
锁竞争
# pidstat -w -I -p 30372 5
Linux 2.6.32-431.23.3.el6.x86_64 (dorado) 2016年09月25日 _x86_64_ (1 CPU)
21时17分45秒 PID cswch/s nvcswch/s Command
21时17分50秒 30372 0.00 0.00 java
21时17分55秒 30372 0.00 0.00 java
21时18分00秒 30372 0.00 0.00 java
21时18分05秒 30372 0.00 0.00 java
每5秒打印pid为30372的上下文切换情况:
- cswch/s:让步式上下文切换,每秒次数
- nvcswch/s:抢占式上下文切换(本文后续说明),每秒次数
Java应用可能因多线程锁竞争,导致性能问题,或无法扩展。用pidstat -w监控上下文切换,结合一般准则判定Java应用是否存在锁竞争。挂起(如:在遇到锁时阻塞)和恢复,会导致操作系统的让步式上下文切换(Voluntary Context Switch)。所以,锁竞争严重的应用,会出现大量的让步式上下文切换。
本例中,没有任何上下文切换。假设cswch/s为3500即,让步式上下文切换每秒3500次。CPU为2核心,CPU频率是3GHz。计算方法:用3500/2=1750,耗费的时钟周期1750 * 80 000(每次让步式上下文切换的时钟周期) = 140 000 000。140 000 000/3 000 000 000=4.7%。根据一般准则,让步式上下文切换时钟周期占用3% ~ 5%,说明Java应用面临锁竞争。
抢占式上下文切换
让步式上下文切换,通常是线程主动释放CPU(如:在遇到锁时阻塞),抢占式上下文切换代表线程因为被分配的时间片用尽被迫放弃CPU或被其他优先级更高的线程所抢占。抢占式上下文切换率高,说明预备运行的线程数多于可用的虚拟处理器数,用vmstat可以看到很长的运行队列、很高的CPU使用率、很大的线程迁移数。
减少应用线程数,用taskset将应用分配给特定的处理器组,可以减少抢占式上下文切换。
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于