背景
近期,在12服务器上测试时发现,多线程工具开满核后,cpu只能占到50%,占不上去。故今天花了一天的时间,专门解决cpu占不上去的问题。
说明:查看系统CPU负载及使用率的命令为:top vmstat
- top 命令:查看进程级别的cpu使用情况。
- vmstat 命令:查看系统级别的cpu使用情况。
说明:
- r: 表示系统中 CPU 等待处理的线程。由于 CPU 每次只能处理一个线程,所以,该数值越大,通常表示系统运行越慢。
- us:用户模式消耗的 CPU 时间百分比。该值较高时,说明用户进程消耗的 CPU 时间比较多,比如,如果该值长期超过 50%,则需要对程序算法或代码等进行优化。
- sy:内核模式消耗的 CPU 时间百分比。
- wa:IO 等待消耗的 CPU 时间百分比。该值较高时,说明 IO 等待比较严重,这可能磁盘大量作随机访问造成的,也可能是磁盘性能出现了瓶颈。
- id:处于空闲状态的 CPU 时间百分比。如果该值持续为 0,同时 sy 是 us 的两倍,则通常说明系统则面临着 CPU 资源的短缺。
过程
IO占用
首先,我猜想是不是因为IO占用太多,导致cpu占不上去,于是去查了一下IO占用:
说明:iostat
从系统开机到当前执行时刻的统计信息
- Avg-cpu:总体cpu使用情况统计。
- Iowait:cpu用于等待io请求的完成时间。
- Device:各磁盘设备的IO统计信息。各列含义如下:
- Device: 以sdX形式显示的设备名称
- tps: 每秒进程下发的IO读、写请求数量
- KB_read/s: 每秒从驱动器读入的数据量,单位为K。
- KB_wrtn/s: 每秒从驱动器写入的数据量,单位为K。
- KB_read: 读入数据总量,单位为K。
- KB_wrtn: 写入数据总量,单位为K。
说明:iostat –x –k –d 1 2
每隔1S输出磁盘IO的详细详细,总共采样2次。
- -x:输出更详细的io设备统计信息
- -k/-m:输出结果以kB/mB为单位
- -d:单独输出device结果,不包括cpu结果
- Interval/count:每次输出间隔时间,count表示输出次数,不带count表示循环输出
- 更多选项,可以使用man iostat查看
各列含义如下:
- rrqm/s: 每秒对该设备的读请求被合并次数,文件系统会对读取同块(block)的请求进行合并
- wrqm/s: 每秒对该设备的写请求被合并次数
- r/s: 每秒完成的读次数
- w/s: 每秒完成的写次数
- rkB/s: 每秒读数据量(kB为单位)
- wkB/s: 每秒写数据量(kB为单位)
- avgrq-sz:平均每次IO操作的数据量(扇区数为单位)
- avgqu-sz: 平均等待处理的IO请求队列长度
- await: 平均每次IO请求等待时间(包括等待时间和处理时间,毫秒为单位)
- svctm: 平均每次IO请求的处理时间(毫秒为单位)
- %util: 采用周期内用于IO操作的时间比率,即IO队列非空的时间比率
重点关注参数:
1、iowait% 表示CPU等待IO时间占整个CPU周期的百分比,如果iowait值超过50%,或者明显大于%system、%user以及%idle,表示IO可能存在问题。
2、avgqu-sz 表示磁盘IO队列长度,即IO等待个数。
3、await 表示每次IO请求等待时间,包括等待时间和处理时间
4、svctm 表示每次IO请求处理的时间
5、%util 表示磁盘忙碌情况,一般该值超过80%表示该磁盘可能处于繁忙状态。
结果发现IO占用正常,于是排除了IO的问题。
内存占用
其次,想到是否因为内存占不上去,导致实际执行线程数小于设定的线程数,于是导致了cpu占不上去。
此时,我换了一台可以正常跑的机器,开同样的线程数,观察了一下内存占用。发现两者内存占用一致。
于是,排除了内存占用的问题。
僵尸进程
再想,有没有可能是因为僵尸进程导致了cpu占不上去呢?于是top一下:
发现没有僵尸进程。
CPU主动降频
最后,有同事提示,是否因为cpu主动降频了,所以导致cpu占不上去。于是专门百度了一下CPU降频的相关知识。
调节器governor可用来控制CPU频率,可选如下:
|
内核模块 |
调节器名称 |
功能 |
|
cpufreq_ondemand |
ondemand |
按需调节,内核提供的功能,不是很强大,但有效实现了动态频率调节 |
|
cpufreq_powersave |
powersave |
省电模式,通常以最低频率运行, |
|
cpufreq_userspace |
userspace |
用户模式,一些调频工具软件需要在此模式下才能运行 |
|
cpufreq_conservative |
conservative |
“保守”模式,类似于ondemand,但调整相对较缓 |
|
N/A |
performance |
不降频 |
查看当前的调节器:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
发现当前使用的是powersave,省电模式,确实会自动降频。于是修改当前模式为performance:
echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
此时去跑多线程程序,发现cpu可以占上去了。
至此,问题解决。
总结
此次cpu占不上去,排查到最后,发现是因为降频导致的。以后可以先通过如下命令查看当前使用的是哪种调节器:
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
确认是否使用了降频模式,然后再去排查其他可能情况。
补充说明:
performance : CPU 会固定工作在其支持的最高运行频率上;
powersave : CPU 会固定工作在其支持的最低运行频率上。因此这两种 governors 都属于静态 governor ,即在使用它们时 CPU 的运行频率不会根据系统运行时负载的变化动态作出调整。这两种 governors 对应的是两种极端的应用场景,使用 performancegovernor 体现的是对系统高性能的最大追求,而使用 powersave governor 则是对系统低功耗的最大追求。
Userspace :最早的 cpufreq 子系统通过 userspace governor 为用户提供了这种灵活性。系统将变频策略的决策权交给了用户态应用程序,并提供了相应的接口供用户态应用程序调节CPU 运行频率使用。(可以使用 Dominik 等人开发了 cpufrequtils 工具包 )
ondemand : userspace 是内核态的检测,效率低。而 ondemand 正是人们长期以来希望看到的一个完全在内核态下工作并且能够以更加细粒度的时间间隔对系统负载情况进行采样分析的 governor 。
conservative : ondemand governor 的最初实现是在可选的频率范围内调低至下一个可用频率。这种降频策略的主导思想是尽量减小对系统性能的负面影响,从而不会使得系统性能在短时间内迅速降低以影响用户体验。但是在 ondemand governor 的这种最初实现版本在社区发布后,大量用户的使用结果表明这种担心实际上是多余的, ondemand governor 在降频时对于目标频率的选择完全可以更加激进。因此最新的 ondemand governor 在降频时会在所有可选频率中一次性选择出可以保证 CPU 工作在 80% 以上负荷的频率,当然如果没有任何一个可选频率满足要求的话则会选择CPU 支持的最低运行频率。大量用户的测试结果表明这种新的算法可以在不影响系统性能的前提下做到更高效的节能。在算法改进后, ondemand governor 的名字并没有改变,而 ondemandgovernor 最初的实现也保存了下来,并且由于其算法的保守性而得名 conservative 。
参考链接
IO占用:https://www.cnblogs.com/ultranms/p/9327784.html
查看进程占用cpu、内存、io信息:http://blog.51cto.com/liuqun/2049656
查看CPU负载及使用率:http://www.cnblogs.com/brightbrother/p/8124915.html
Cpu频率调节:http://blog.sina.com.cn/s/blog_62218fc80100rko7.html
不同频率控制方式说明:https://blog.csdn.net/lizhiqiang50/article/details/50992847