Java性能优化之操作系统层面优化
目前常用的操作系统分为:windows,Unix(Linux),我们会分别介绍在不同系统上的调优。
一,概念
性能监控:一种以非侵入方式收集或查看应用运行性能数据的活动,通常是指在生产,质量评估, 开发环境中实施的带有预防或主动性的活动。
性能分析:一种以侵入方式收集运行性能数据的活动,会影响应用的吞吐量或响应性。
性能调优:一种为改善应用响应性或吞吐量而更改参数,源代码或属性配置的活动。
CPU:中央处理器,从内存中获取数据然后进行计算的处理单元,
CPU使用率:分为用户态CPU使用率和系统态CPU使用率,用户态CPU使用率是指执行应用程序代码的时间占总CPU时间的百分比,系统态CPU指应用执行操作系统调用的时间占用总CPU的时间的百分比。例如I/O设备之间的交互教师使用系统态CPU,所以我们想要的结果是系统态的CPU的使用率为0%,即降低系统态CPU的使用率
CPI:(Cycle Per instruction):每条指令执行时所花费的平均时钟周期数。(时钟周期:也为震荡周期,定义为时钟脉冲的倒数,是计算机中最基本,最小的时间单位,在一个时钟周期内,CPU仅完成一个最基本的动作,例如1MHZ的时钟频率,则时钟周期为1us,对计算机来说,时钟频率越高,计算机的工作速度就越快)(指令周期:执行一条指令所需的时间,指令不同,所需的周期数也不同)。
二,监控CPU的使用率:
WINDOWS:
任务管理器
上面有CPU的使用率,内存的使用率,进程数,线程,CPU的执行速度等
Performance Monitor(性能监视器)
不同版本的WINDOWS上的性能监视器是不同的,性能监视器使用了性能对象的概念,性能对象分为网络,内存,处理器,线程,进程,网络接口,逻辑磁盘等,每一类都含有特定的性能属性或计数器。可以作为监控的性能统计数据。
红线表示进程信息,性能监视器的滑动串口默认显示最近60秒的性能统计数据,可在图形界面点击右键,设置一些属性。
可以手动的添加各种性能对象,通过在图像区域点击右键-》选择添加计数器-》选择计数器Processor对象,选择计数器%User time表示用户态CPU使用率,选择计数器%Privileged Time表示系统态CPU使用率,点击Add -》确定。
命令行工具:typeperf
typeperf可以在命令终端运行,也可以写在脚本语句中,写法:
typeperf "\Processor(_Total)\%User Time"
Linux:
监控命令:
gnome-system-monitor:
vmstat:
[land@localhost network-scripts]$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 60936 81388 36 203572 1 11 211 13 116 123 0 1 96 2 0
vmstat显示所有虚拟处理器的总CPU使用率,vmstat命令行可以设定报告的时间间隔,如果不指定vmstat的报告间隔,则输出系统最近一次启动以来的总CPU的使用率。us是用户态CPU使用率,sy是系统态CPU使用率,id是空闲率或CPU可用率。
mpstat:
[land@localhost network-scripts]$ mpstat
Linux 3.10.0-862.el7.x86_64 (localhost.localdomain) 12/12/2018 _x86_64_ (4 CPU)
03:33:50 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
03:33:50 AM all 0.42 0.00 0.86 2.06 0.00 0.04 0.00 0.00 0.00 96.62
top命令:
不仅包括CPU的使用率,也包括进程统计数据和内存使用率,
CPU的调度程序运行队列
监控CPU调度程序运行队列对于分辨系统是否满负荷有很重要的意义,运行队列中就是已经准备好运行,正在等待可用CPU的轻量级进程。如果准备运行的进程数量过多,就是导致调度队列过长,则系统有可能已经饱和。
一般原则:如果在很长一段时间里,运行队列的长度一直都超过虚拟处理器个数的1倍,就需要注意,如果运行队列的长度超多虚拟处理器个数的3-4倍或更高,则需要立刻采取行动。
解决队列过长的两种方法:⑴增加CPU以分担负载或减少处理器的负载量⑵分析系统中运行的应用,改进CPU使用率,即减少应用运行所需CPU周期的方法,如减少垃圾收集器的频率,或使用更少的CPU指令算法来实现相同的功能。
WINDOWS:
通过在性能监视器图中-》右键-》添加计数器-》system->Processor Queue Length-》确定。
当然也可以使用typeperf命令来监视运行队列的长度。
Linux:
使用vmstat命令可以监控运行队列的长度,vmstat输出的第一列是运行队列长度,值是运行队列中轻量级进程的实际数量。
[land@localhost ~]$ vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 43528 61980 36 240280 0 9 271 21 96 91 0 1 96 2 0
监控锁竞争:
Java5以上的锁优化机制。线程通过忙循环自旋尝试获取锁,如果若干次忙循环自旋后仍然没有成功,则挂起该线程,等待被唤醒再次尝试获取该锁。挂起和唤醒线程会导致操作系统的让步式上下文切换,因此锁竞争严重的应用程序会表现出大量的让步式上下文切换,Solaris上可以通过mpstat的csw列监控上下文切换,它是上下文切换的总和。icsw列是抢占式上下文切换,因此让步式上下文切换的次数是csw-icsw.让步式上下文切换耗时的时钟周期代价非常高,通常高达80000个时钟周期。
对于任何Java应用来说,如果让步式上下文切换占去它5%或者更过时钟周期,说明可能遇到锁竞争,估算让步式上下文切换:mpstat间隔内的线程上下文csw减去抢占式上下文(icsw),乘80000,除以间隔内总的时间周期。
监控网络I/O使用率:
WINDOWS:
在性能监视器中,通过添加性能计数器就可以,性能对象为Network Interface/Bytes Total/sec获得,通配符*表示报告的是系统所有网络接口的总带宽。也可以使用typeperf \Network Interface(*)\Bytes Total/sec查看网络接口名。然后用想要打算监控的网络接口替换通配符*。
查看网络带宽可以添加Network Interface/Current Bandwidth对象,查看网络的带宽
硬盘I/O的使用率:
硬盘I/O可以看做是磁盘使用情况有用的监控数据,Linux和Solaris可以使用iostat来监控系统的磁盘使用情况。Linux可以使用iostat -xm监控磁盘I/O使用率和系统态CPU使用率。
[root@localhost ~]# iostat -xm
Linux 3.10.0-862.el7.x86_64 (localhost.localdomain) 12/12/2018 _x86_64_(4 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.36 0.00 0.80 2.08 0.00 96.76
Device: rrqm/s wrqm/s r/s w/s rMB/s wMB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
sda 0.87 9.86 20.22 0.64 1.06 0.05 109.22 0.53 25.25 25.48 18.06 3.41 7.12
scd0 0.00 0.00 0.02 0.00 0.00 0.00 72.41 0.00 49.83 49.83 0.00 40.90 0.07
dm-0 0.00 0.00 19.85 0.56 1.05 0.01 106.59 0.53 25.84 26.25 11.10 3.44 7.03
dm-1 0.00 0.00 1.04 9.94 0.01 0.04 8.21 0.58 52.69 11.14 57.03 0.27 0.30
[root@localhost ~]#
sda磁盘的使用率为 7.12%,系统态CPU为0.8%,用户态CPU0.36%。
参考《Java 性能优化权威指南》 Charlie Hunt Binu John 著