1.多线程监控上下文切换频率
linux系统下,使用内核提供的vmstat
如vmstat 2 1 表示采集间隔2秒采样1次
vmstat各字段说明
1、procs
r:表示运行和等待CPU时间片的进程数(就是说多少个进程真的分配到CPU),这个值如果长期大于系统CPU个数,说明CPU不足,需要增加CPU
b:表示在等待资源的进程数,比如正在等待I/O或者内存交换等。
2、memory
swpd:表示切换到内存交换区的内存大小,即虚拟内存已使用的大小(单位KB),如果大于0,表示你的机器物理内存不足了,如果不是程序内存泄露的原因,那么你该升级内存了或者把耗内存的任务迁移到其他机器。
free:表示当前空闲的物理内存
buff:表示baffers cached内存大小,也就是缓冲大小,一般对块设备的读写才需要缓冲
Cache:表示page cached的内存大小,也就是缓存大小,一般作为文件系统进行缓冲,频繁访问的文件都会被缓存,如果cache值非常大说明缓存文件比较多,如果此时io中的bi比较小,说明文件系统效率比较好
3、swap
si:表示有磁盘调入内存,也就是内存进入内存交换区的内存大小;通俗的讲就是 每秒从磁盘读入虚拟内存的大小,如果这个值大于0,表示物理内存不够用或者内存泄露了,要查找耗内存进程解决掉。
so:表示由内存进入磁盘,也就是由内存交换区进入内存的内存大小。
注意:一般情况下si、so的值都为0,如果si、so的值长期不为0,则说明系统内存不足,需要增加系统内存
4、io
bi:表示由块设备读入数据的总量,即读磁盘,单位kb/s
bo:表示写到块设备数据的总量,即写磁盘,单位kb/s
注意:如果bi+bo的值过大,且wa值较大,则表示系统磁盘IO瓶颈
5、system
in:表示某一时间间隔内观测到的每秒设备终端数
cs:表示每秒产生的 上下文切换次数,例如我们调用系统函数,就要进行上下文切换,线程的切换,也要进程上下文切换,这个值要越小越好,太大了,要考虑调低线程或者进程的数目,例如在apache和nginx这种web服务器中,我们一般做性能测试时会进行几千并发甚至几万并发的测试,选择web服务器的进程可以由进程或者线程的峰值一直下调,压测,直到cs到一个比较小的值,这个进程和线程数就是比较合适的值了。系统调用也是,每次调用系统函数,我们的代码就会进入内核空间,导致上下文切换,这个是很耗资源,也要尽量避免频繁调用系统函数。上下文切换次数过多表示你的CPU大部分浪费在上下文切换,导致CPU干正经事的时间少了,CPU没有充分利用,是不可取的。
注意:
这两个值越大,则由内核消耗的CPU就越多
6、CPU
us:表示用户进程消耗的CPU时间百分比,us值越高,说明用户进程消耗CPU时间越多,如果长期大于50%,则需要考虑优化程序或者算法
sy:表示系统内核进程消耗的CPU时间百分比,一般来说us+sy应该小于80%,如果大于80%,说明可能存在CPU瓶颈
id:表示CPU处在空间状态的时间百分比
wa:表示IP等待所占用的CPU时间百分比,wa值越高,说明I/O等待越严重,根据经验wa的参考值为20%,如果超过20%,说明I/O等待严重,引起I/O等待的原因可能是磁盘大量随机读写造成的,也可能是磁盘或者监控器的贷款瓶颈(主要是块操作)造成的
综上所述,如果评估CPU,需要重点关注procs项的r列值和CPU想的us、sy、wa列的值
2.监视指定进程的上下文切换情况
pidstat 的用法:
常用的参数:
- -u:默认的参数,显示各个进程的cpu使用统计
- -r:显示各个进程的内存使用统计
- -d:显示各个进程的IO使用情况
- -p:指定进程号
- -w:显示每个进程的上下文切换情况
- -t:显示选择任务的线程的统计信息外的额外信息
- -T { TASK | CHILD | ALL }
这个选项指定了pidstat监控的。TASK表示报告独立的task,CHILD关键字表示报告进程下所有线程统计信息。ALL表示报告独立的task和task下面的所有线程。
注意:task和子线程的全局的统计信息和pidstat选项无关。这些统计信息不会对应到当前的统计间隔,这些统计信息只有在子线程kill或者完成的时候才会被收集。 - -V:版本号
- -h:在一行上显示了所有活动,这样其他程序可以容易解析。
- -I:在SMP环境,表示任务的CPU使用率/内核数量
- -l:显示命令名和所有参数
pidstat [ 选项 ] [ <时间间隔> ] [ <次数> ]
- PID:进程id
- Cswch/s:每秒主动任务上下文切换数量
- Nvcswch/s:每秒被动任务上下文切换数量
- Command:命令名
3.发现排查死锁
利用jdk提供的工具定位死锁问题:
- jps 显示所有当前Java虚拟机进程名及pid.
- jstack 进程号 打印进程堆栈信息。
死锁关键字提示 found one Java-level deadlock,还能看到代码执行停留在什么位置发生阻塞。
4.检查堆内存中的对象
利用jdk提供的工具:
- jps 显示所有当前Java虚拟机进程名及pid.
- jmap -histo 进程号 打印进程堆栈信息。
5.查看虚拟机GC情况
jstat -gc 进程号 间隔毫秒 查询次数
新生代Eden区(E,表示Eden)使用了2%的空间,两个Survivor区(S0、S1,表示Survivor0、Survivor1)都是空的。
老年代(O,表示Old)和永久带(P。表示Permanent)则分别使用了0%和13.84%的空间。
程序运行以来共发生Minor GC(YGC,表示Young GC)0次,总共耗时0秒;发生Full GC(FGC,表示Full GC)0次,Full GC共耗时(FGCT,Full GC Time)为0秒,所有GC总耗时(GCT,表示GC Time)0秒。