Linux性能优化之CPU利用率

写在前面

本文看下CPU使用率相关内容。

1:Linux是如何维护CPU时间的?如何查看CPU使用率?

1.1:Linux是如何维护CPU时间的?

先来看下节拍率的概念,通过HZ表示,一般是100,250,1000这样的值,如下查看:

复制代码
root@dongyunqi:/home/dongyunqi/study/jdk1.8.0_152/jdk8u482-b08# grep 'CONFIG_HZ=' /boot/config-$(uname -r)
CONFIG_HZ=1000

代表每秒会发生1000次切换,这每一次切换,是一次中断,两次中断之间的时间叫做一个滴答,即tick。那么cpu时间片和tick是什么关系呢?是这样子的,linux会将时间片定义为tick的整数值,比如一个时间片等于3*tick,这个时候,一个CPU时间片的长度就是3毫秒了。那CPU时间是通过时间片切换次数,再换算成滴答数,从而得到运行时间的吗?不是的,因为这样计算的结果误差太大了。试想下CPU时间只能以毫秒为单位,力度也太大了。其实CPU时间的计算,在linux中是通过TSC,即time stamp counter来计算的,其计算的精度更高,可以到纳秒级,精度很高很高了。

那么该如何查看CPU时间,通过命令cat /proc/stat | grep ^cpu可以看整个系统的CPU时间,如下:

复制代码
root@dongyunqi:/home/dongyunqi/study# cat /proc/stat | grep ^cpu
cpu  1935124 1976 5114477 4277863 2086 0 20396 0 0 0
cpu0 1935124 1976 5114477 4277863 2086 0 20396 0 0 0

每一列的含义如下:

复制代码
user(通常缩写为 us),代表用户态 CPU 时间。注意,它不包括下面的 nice 时间,但包括了 guest 时间。
nice(通常缩写为 ni),代表低优先级用户态 CPU 时间,也就是进程的 nice 值被调整为 1-19 之间时的 CPU 时间。这里注意,nice 可取值范围是 -20 到 19,数值越大,优先级反而越低。
system(通常缩写为 sys),代表内核态 CPU 时间。
idle(通常缩写为 id),代表空闲时间。注意,它不包括等待 I/O 的时间(iowait)。
iowait(通常缩写为 wa),代表等待 I/O 的 CPU 时间。
irq(通常缩写为 hi),代表处理硬中断的 CPU 时间。
softirq(通常缩写为 si),代表处理软中断的 CPU 时间。
steal(通常缩写为 st),代表当系统运行在虚拟机中的时候,被其他虚拟机占用的 CPU 时间。
guest(通常缩写为 guest),代表通过虚拟化运行其他操作系统的时间,也就是运行虚拟机的 CPU 时间。
guest_nice(通常缩写为 gnice),代表以低优先级运行虚拟机的时间。

当然一般我们更关心的是进程的CPU时间,可以通过/proc/[pid]/stat查看。

1.2:如何查看CPU使用率?

我们知道了可以通过查看相关的系统数据来获取不同状态的CPU时间,那么当我们要计算的时候难道要自己来计算吗?这也太麻烦了,当然不用,Linux已经给我们准备好了各种命令了,比如最常用的top,以及pidstat等。

复制代码
^Croot@dongyunqi:/home/dongyunqi/study# pidstat 5 1
Linux 6.8.0-106-generic (dongyunqi)     04/03/2026      _x86_64_        (1 CPU)

05:34:43 PM   UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
05:34:48 PM     0      6253    0.00    0.20    0.00    0.20    0.20     0  kworker/u256:2-events_power_efficient
05:34:48 PM     0      6273    0.00    0.20    0.00    0.00    0.20     0  kworker/0:2-events
05:34:48 PM     0      6363    0.00    0.60    0.00    0.00    0.60     0  pidstat

Average:      UID       PID    %usr %system  %guest   %wait    %CPU   CPU  Command
Average:        0      6253    0.00    0.20    0.00    0.20    0.20     -  kworker/u256:2-events_power_efficient
Average:        0      6273    0.00    0.20    0.00    0.00    0.20     -  kworker/0:2-events
Average:        0      6363    0.00    0.60    0.00    0.00    0.60     -  pidstat

2:实战CPU问题排查

我们准备如下的程序:

java 复制代码
package dongshi.daddy.zhengxi;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class ManyCpu {

    private static List<Long> myList = new ArrayList<>();
    public static void main(String[] args) {
        new Thread(() -> {
            while (true) {
                int aa = 88888888 + new Random().nextInt(10000);
                int bb = 98888888 + new Random().nextInt(10000);
                System.out.println(aa * bb);
                System.out.println((aa + 1) * bb);
                System.out.println(aa * (bb + 1));
            }
        }, "thread-testmanycpu").start();

    }
}

编译运行:

复制代码
root@dongyunqi:/home/dongyunqi/study# javac -d . ManyCpu.java
root@dongyunqi:/home/dongyunqi/study# ls
cpu_stress.sh  dongshi  jdk1.8.0_152  ManyCpu.java  packages
root@dongyunqi:/home/dongyunqi/study# java dongshi.daddy.zhengxi.ManyCpu

使用pidstat查看cpu使用率:

复制代码
root@dongyunqi:/home/dongyunqi# top
top - 17:47:35 up 1 day,  8:13,  6 users,  load average: 1.71, 1.07, 1.00
Tasks: 230 total,   1 running, 229 sleeping,   0 stopped,   0 zombie
%Cpu(s): 98.0 us,  2.0 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1920.3 total,    292.8 free,    509.6 used,   1296.7 buff/cache
MiB Swap:   1899.0 total,   1898.7 free,      0.3 used.   1410.7 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   6723 root      20   0 2375824  41948  16852 S  98.7   2.1   1:26.84 java
...

可以看到我们的Java进程,已经占用了98.7%的CPU了,接着来看下进程中哪个线程占用了CPU:

复制代码
root@dongyunqi:/home/dongyunqi# top -Hp 6723
top - 17:49:19 up 1 day,  8:15,  6 users,  load average: 1.18, 1.06, 1.00
Threads:  11 total,   1 running,  10 sleeping,   0 stopped,   0 zombie
%Cpu(s): 98.7 us,  1.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1920.3 total,    292.8 free,    509.5 used,   1296.8 buff/cache
MiB Swap:   1899.0 total,   1898.7 free,      0.3 used.   1410.8 avail Mem

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND
   6733 root      20   0 2375824  41948  16852 R  95.3   2.1   2:59.11 thread-testmany
...

可以看到线程ID是6733,接着我们需要查看该线程执行的方法是啥,命令jstack [进程id] | grep [线程id十六进制]如下:

红框就是造成CPU高的位置了。

写在后面

参考文章列表

相关推荐
Decay__2 小时前
05_MySQL 常用 SQL 大全 —— 诊断、管理、优化辅助 SQL 与三大系统库速查
运维·数据库·sql·mysql·架构
贞明电子4 小时前
工业三色报警灯怎么接入项目系统?开关量与RS485控制应用指南
运维·网络·微信公众平台·贞明电子
学长毕设5 小时前
基于SpringBoot的实验室资产管理系统
java·spring boot·后端
HideF5 小时前
Linux
linux·服务器·网络
万联WANFLOW5 小时前
海外网络故障怎么排查?Cloudflare 三季度断网报告解读与 mtr 实战
运维·网络·故障分析
zzu123zsw6 小时前
从臃肿的模板调用到声明式契约:深入 UniHttp 动态代理与多渠道生命周期扩展
java·spring boot·microsoft·unihttp
Ruiery7 小时前
Linux 6.6内核内存管理深度解析(十三):slab/slub 分配器
linux·运维·服务器
源码集结号7 小时前
云诊所门诊系统源码,基于SpringBoot+Vue.js架构,支持多租户设计与Docker容器化部署
java·spring boot·源码·医院信息系统·门诊系统·诊所系统
论文复现现场7 小时前
WRF、FEA 能用 L40S 加速吗?求解器检查、断点恢复与长期运行
java·数据库·算法·wrf·有限元分析·gpu计算·断点续算
啃瓜子的松鼠7 小时前
泛微OAe9-后端二开异步调用
java