linux 性能分析-负载

一、系统平均负载

1.概念

平均负载是指单位时间内,系统处于可运行状态和不可中断状态的平均进程数,也就是平均活跃进程数。它不仅包括了正在使用 CPU 的进程,还包括等待 CPU 和等待 I/O 的进程

它和 CPU 使用率并没有直接关系

2.负载高的场景

2.1 cpu密集型

CPU 密集型进程,使用大量 CPU 会导致平均负载升高,此时系统负载和cpu使用率高是一致的;

2.2 I/O密集型

I/O 密集型进程,等待 I/O 也会导致平均负载升高,但 CPU 使用率不一定很高;

2.3 cpu等待调度

大量等待 CPU 的进程调度也会导致平均负载升高,此时的 CPU 使用率也会比较高。

3.环境介绍

3.1 服务器配置

shell 复制代码
[root@t3-tkhijbs-tkylgw-app01 ~]# cat /proc/cpuinfo |grep -i processor
processor	: 0
processor	: 1
processor	: 2
processor	: 3

3.2 安装压测工具

使用stress命令进行压力测试,sysstat包生成pidstat命令,查看进程信息

复制代码
yum -y install stress sysstat

3.3 stress命令基本使用

shell 复制代码
1.-c: 
	完整参数:--cpu N 
	作用:产生N个进程,每个进程都循环调用sqrt函数产生CPU压力
2.-i:
	完整参数:--io N
	作用:产生N个进程,每个进程循环调用sync将内存缓冲区内容写到磁盘上,产生IO压力。通过系统调用sync刷新内存缓冲区数据到磁盘中,以确保同步。如果缓冲区内数据较少,写到磁盘中的数据也较少,不会产生IO压力。在SSD磁盘环境中尤为明显,很可能iowait总是0,却因为大量调用系统调用sync,导致系统CPU使用率sys 升高

3.-d: 
	完整参数:--hdd N
	作用:产生N个不断执行write和unlink函数的进程(创建文件,写入内容,删除文件)

4.-t:
	完整参数: --timeout N
	作用:在N秒后结束程序

4.cpu密集型压测

对4个核心进行压力测试,超时时间为600秒

shell 复制代码
stress -c 4 -t 600

查看系统负载,发现系统负载变成了5.86.使用top查看,还在持续增长

shell 复制代码
[root@t3-tkhijbs-tkylgw-app01 ~]# uptime
 17:05:45 up 33 days,  3:22,  2 users,  load average: 5.86, 2.37, 0.91

使用top或者pidstat查看cpu使用率。这里看出4个进程,每个进程的CPU使用率都是100%

c 复制代码
05:30:53 PM   UID       PID    %usr %system  %guest    %CPU   CPU  Command
05:30:58 PM     0         1    0.00    0.20    0.00    0.20     3  systemd
05:30:58 PM  4000      5297    0.00    0.20    0.00    0.20     2  zabbix_agentd
05:30:58 PM  4000      5337    0.20    0.00    0.00    0.20     2  filebeat
05:30:58 PM  4300     18001    0.20    0.00    0.00    0.20     0  easy_collector
------------------ 可以看出这4个进程每个进程的使用率都是100%
05:30:58 PM     0     21038  100.00    0.00    0.00  100.00     1  stress
05:30:58 PM     0     21039   99.80    0.00    0.00   99.80     2  stress
05:30:58 PM     0     21040   99.80    0.00    0.00   99.80     3  stress
05:30:58 PM     0     21041   99.80    0.00    0.00   99.80     0  stress
--------------------
05:30:58 PM     0     21084    0.00    0.20    0.00    0.20     0  pidstat

5.I/O密集型压测

运行 stress 命令,但这次模拟 I/O 压力。

5.1.查看磁盘容量

shell 复制代码
[root@t3-tkhijbs-tkylgw-app01 ~]# df -Th
Filesystem              Type      Size  Used Avail Use% Mounted on
/dev/mapper/rootvg-root xfs       191G  3.8G  187G   2% /

5.2 开始I/O操作

shell 复制代码
stress -d 4 -t 600

再次查看磁盘大小,使用容量已经到达了8G

shell 复制代码
[root@t3-tkhijbs-tkylgw-app01 ~]# df -Th
Filesystem              Type      Size  Used Avail Use% Mounted on
/dev/mapper/rootvg-root xfs       191G  8.0G  183G   5% /

5.3 查看负载

使用top 查看,负载已经变成了4.69. iowaite 已经变成了55%,

shell 复制代码
top - 11:06:46 up 38 days, 21:23,  3 users,  load average: 4.69, 2.24, 0.96
%Cpu(s):  0.2 us, 41.8 sy,  0.1 ni,  2.5 id, 55.0 wa,  0.0 hi,  0.4 si,  0.0 st

可以看到stess的状态全部处于D状态,但是每个进程的CPU的使用率并不是很高。

shell 复制代码
113414 root      20   0    8216   1124     32 D  44.0  0.0   1:38.11 stress                                                           
113416 root      20   0    8216   1124     32 D  42.0  0.0   1:36.08 stress                                                           
113413 root      20   0    8216   1124     32 D  41.0  0.0   1:40.00 stress                                                           
113415 root      20   0    8216   1124     32 D  40.3  0.0   1:36.71 stress

5.4 查看磁盘I/O

shell 复制代码
yum -y install iotop
shell 复制代码
基本用法:
iotop -o: 仅显示实际执行I/O的进程或线程
iotop -b:非交互模式,批量处理用来记录日志的
iotop -n [次数]: 设定循环几次
iotop -p [进程/线程] :查看指定进程的读写
iotop -P 只显示进程

查看结果如下:

shell 复制代码
Total DISK READ :       0.00 B/s | Total DISK WRITE :       3.95 G/s
Actual DISK READ:       0.00 B/s | Actual DISK WRITE:       2.41 G/s
   TID  PRIO  USER     DISK READ  DISK WRITE  SWAPIN      IO    COMMAND
113079 be/4 root        0.00 B/s    0.00 B/s  0.00 % 61.41 % [kworker/u256:2]
114406 be/4 root        0.00 B/s  516.66 M/s  0.00 % 36.82 % stress -d 4 -t 600
114409 be/4 root        0.00 B/s  762.88 M/s  0.00 % 34.96 % stress -d 4 -t 600
114408 be/4 root        0.00 B/s  711.30 M/s  0.00 % 32.77 % stress -d 4 -t 600
114407 be/4 root        0.00 B/s  544.27 M/s  0.00 % 32.36 % stress -d 4 -t 600

解释:

Actual DISK WRITE: 是实际磁盘写入的数据

二、线程

这里要先讲一下线程,才能为下边单进程的cpu使用率做铺垫

1.线程概念

线程是进程的子单位,是真正执行任务的单元。而进程是资源分配的单位

2.安装pidstat命令

sehll 复制代码
yum -y install sysstat

3.启动多线程

3.1 代码内容

使用python生成多个线程,代码如下

c 复制代码
cat test.py

from concurrent.futures import  ThreadPoolExecutor
import time

# 启动线程池,启动10个线程
spool = ThreadPoolExecutor(10)

task_list = [ i for i in range(100)]

def test(list):
    print(list)
    time.sleep(1000)

def main():
      for i in task_list:
          spool.submit(test,i)

if __name__ == "__main__":
    main()

2.2 启动多线程

shell 复制代码
python3 test.py

4.查看进程

c 复制代码
[root@node4 test]# ps aux |grep test
root      22200  0.2  1.3 937428 13372 pts/0    Sl+  05:00   0:00 python3 test.py

4.1 查看进程中的线程

方法1:top
shell 复制代码
top -H -p 22200
方法2:pidstat
shell 复制代码
pidstat -t -p 22200

内容如下:

这里可以看出,python启动的程序一共有10个线程

c 复制代码
[root@node4 ~]# pidstat -t  -p 22200
Linux 3.10.0-693.el7.x86_64 (node4) 	04/29/2024 	_x86_64_	(4 CPU)

03:30:16 AM   UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
03:30:16 AM     0     21582         -    0.00    0.00    0.00    0.00     2  python3
03:30:16 AM     0         -     21582    0.00    0.00    0.00    0.00     2  |__python3
03:30:16 AM     0         -     21583    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21584    0.00    0.00    0.00    0.00     0  |__python3
03:30:16 AM     0         -     21585    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21586    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21587    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21588    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21589    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21590    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21591    0.00    0.00    0.00    0.00     3  |__python3
03:30:16 AM     0         -     21592    0.00    0.00    0.00    0.00     3  |__python3

解释:

shell 复制代码
TGID : 进程ID
TID: 线程ID

三、单进程的cpu使用率

1.cpu使用率的概念

上述中讲了平均负载的概念,平均负载与CPU使用率并没有直接的关系。这里来看看cpu使用率到底是什么意思。

1.1 时间片

Linux 作为一个多任务操作系统,将每个 "CPU 的时间" 划分为很短的 "时间片",再通过调度器轮流分配给各个任务使用,因此造成多任务同时运行的错觉。

1.2 cpu时间片相关参数

在top命中可以到一下参数

c 复制代码
%Cpu(s):  1.5 us,  1.5 sy,  0.0 ni, 96.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

解释:

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

1.3 cpu使用率

CPU 使用率,就是除了空闲时间外的其他时间占总 CPU 时间的百分比。

只是在top中把 CPU 时间变换成了 CPU 使用率。

2.单进程多线程cpu超过100

cpu核心数量为8核心

c 复制代码
[root@p0-tkhijbs-jenkins-app01 ~]# cat /proc/cpuinfo |grep processor
processor	: 0
processor	: 1
processor	: 2
processor	: 3
processor	: 4
processor	: 5
processor	: 6
processor	: 7

2.1.代码如下:

这里使用了c语言写了一个简单的多线程的程序。

这里之所以使用的C 是因为C、c++、java语法多线程是真正的使用了多核心技术.而python语言只能使用总核心的一半。不知道是不是我代码的问题

c 复制代码
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
 
void* thread_function(void* arg) {
    while(1) {
        
    }
    return NULL;
}
 
int main() {
    # 这里的8是线程的数量,和cpu的核心的数量一致或者小于即可
    pthread_t threads[8]; 
    int i;
    
    # 这里的6就是上边的生成线程的数量
    for(i = 0; i < 8; i++){
        if(pthread_create(&threads[i], NULL, &thread_function, NULL) != 0) {
            fprintf(stderr, "线程创建失败\n");
            return 1;
        }
    }
 
 	 # 这里的6就是上边的生成线程的数量
    for(i = 0; i < 8; i++){
        pthread_join(threads[i], NULL);
    }
 
    return 0;
}

2.2 编译

如果编译报错:

c 复制代码
[root@p0-tkhijbs-jenkins-app01 ~]# gcc test.c
/tmp/cctoYACU.o: In function `main':
test.c:(.text+0x3f): undefined reference to `pthread_create'
test.c:(.text+0x92): undefined reference to `pthread_join'
collect2: error: ld returned 1 exit statu

解决办法:

c 复制代码
[root@p0-tkhijbs-jenkins-app01 ~]# gcc test.c -lpthread

2.3 运行

c 复制代码
./a.out

2.4 使用top查看负载

基本参数:

shell 复制代码
-b: 以批处理模式运行top命令,不需要交互式操作。输出结果可以重定向或管道符输出到文件或其他命令中
-i: 忽略闲置进程,只显示活跃的进程。活跃进程是指CPU或其他资源使用率高的进程
-d: 指定top命令更新的时间间隔,单位为秒,默认值是3秒
-H: 查看进程的线程
-p: 指定pid

查看命令:

c 复制代码
[root@p0-tkhijbs-jenkins-app01 ~]# top -b -i 
top - 19:28:56 up 1454 days,  1:35,  2 users,  load average: 3.22, 0.77, 0.29
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
29161 root      20   0   22872    376    296 S 762.5  0.0   3:16.54 a.out

......
......
......

top - 19:30:16 up 1454 days,  1:36,  2 users,  load average: 8.23, 2.97, 1.11
  PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
29161 root      20   0   22872    376    296 S 800.0  0.0  13:53.34 a.out

这里看到 a.out程序的%cpu已经达到%800.这里就出现了单进程的cpu使用率超过了100%的现象

2.5 查看a.out的线程

c 复制代码
[root@p0-tkhijbs-jenkins-app01 ~]# pidstat -p 29161 -t 
Linux 3.10.0-693.el7.x86_64 (p0-tkhijbs-jenkins-app01) 	05/07/2024 	_x86_64_	(8 CPU)

07:33:54 PM   UID      TGID       TID    %usr %system  %guest    %CPU   CPU  Command
07:33:54 PM     0     29161         -    0.00    0.00    0.00    0.00     4  a.out
07:33:54 PM     0         -     29161    0.00    0.00    0.00    0.00     4  |__a.out
07:33:54 PM     0         -     29162    0.00    0.00    0.00    0.00     5  |__a.out
07:33:54 PM     0         -     29163    0.00    0.00    0.00    0.00     6  |__a.out
07:33:54 PM     0         -     29164    0.00    0.00    0.00    0.00     0  |__a.out
07:33:54 PM     0         -     29165    0.00    0.00    0.00    0.00     2  |__a.out
07:33:54 PM     0         -     29166    0.00    0.00    0.00    0.00     1  |__a.out
07:33:54 PM     0         -     29167    0.00    0.00    0.00    0.00     3  |__a.out
07:33:54 PM     0         -     29168    0.00    0.00    0.00    0.00     7  |__a.out
07:33:54 PM     0         -     29169    0.00    0.00    0.00    0.00     4  |__a.out
相关推荐
绵绵细雨中的乡音1 小时前
网络基础知识
linux·网络
Peter·Pan爱编程1 小时前
Docker在Linux中安装与使用教程
linux·docker·eureka
kunge20132 小时前
Ubuntu22.04 安装virtualbox7.1
linux·virtualbox
清溪5492 小时前
DVWA中级
linux
Sadsvit3 小时前
源码编译安装LAMP架构并部署WordPress(CentOS 7)
linux·运维·服务器·架构·centos
xiaok3 小时前
为什么 lsof 显示多个 nginx 都在 “使用 443”?
linux
苦学编程的谢4 小时前
Linux
linux·运维·服务器
G_H_S_3_4 小时前
【网络运维】Linux 文本处理利器:sed 命令
linux·运维·网络·操作文本
Linux运维技术栈4 小时前
多系统 Node.js 环境自动化部署脚本:从 Ubuntu 到 CentOS,再到版本自由定制
linux·ubuntu·centos·node.js·自动化
拾心214 小时前
【运维进阶】Linux 正则表达式
linux·运维·正则表达式