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高的位置了。

写在后面

参考文章列表

相关推荐
搞科研的小刘选手10 分钟前
【天津市电源学会主办】第七届能源电力与自动化工程国际学术会议(ICEPAE 2026)
运维·自动化·能源·电力·电气·控制工程·节能
Amctwd12 分钟前
【Python】从Excel中按行提取图片
java·python·excel
恋奴娇17 分钟前
ubuntu 25 突破pipewire 不能以root帐号运行 系统没有声音输入输出设备
linux·运维·ubuntu
啃臭21 分钟前
AOP和反射
java·spring boot
MuYan~27 分钟前
开发环境内网MySQL连接操作文档
运维·服务器
西凉的悲伤28 分钟前
java 使用PNG图片隐写文件
java·图片隐写·png
Bert.Cai29 分钟前
Linux dirname命令详解
linux·运维·服务器
有梦想的小何31 分钟前
Cursor AI 编程实战(篇一):Prompt 与案例总结
java·linux·prompt·ai编程
程序 代码狂人36 分钟前
Linux查询自己环境的一些基础命令
linux·运维·服务器
进击切图仔1 小时前
RAG 加载 pdf 文档
linux·前端·pdf