对于内核线程的CPU使用率高,比如ksoftirqd的CPU使用率高,这种内核线程,直接使用常见的性能分析工具,不太方便

那么这次就说下,如何观察这类内核线程

在说明其之前,先了解一下常见的Linux内核线程,Linux中,用户态进程的祖先,是systemd进程,PID为1,而内核线程呢? 则是2号进程kthreadd进程管理的

其中的关系为 0号为idle进程,系统创建的第一个进程,初始化1号和2号进程后,就变为了空闲任务,方便系统在空闲的时候空转

1号进程负责管理用户态线程

2号进程负责管理内核态线程

对于内核线程,只需要查看2号进程及其子进程即可

ps -f –ppid 2 -p 2

$ ps -f –ppid 2 -p 2

UID         PID   PPID  C STIME TTY          TIME CMD

root          2      0  0 12:02 ?        00:00:01 [kthreadd]

root          9      2  0 12:02 ?        00:00:21 [ksoftirqd/0]

root         10      2  0 12:02 ?        00:11:47 [rcu_sched]

root         11      2  0 12:02 ?        00:00:18 [migration/0]

root      11094      2  0 14:20 ?        00:00:00 [kworker/1:0-eve]

root      11647      2  0 14:27 ?        00:00:00 [kworker/0:2-cgr]

这其中有我们的主角 ksoftirqd,负责处理软中断,每个CPU都有一个

除了kthreadd 和 ksoftirqd之外,还有几个内核线程

kswapd0:用于内存回收

kworker: 用于执行内核工作队列

migration: 负载均衡过程中,讲进程迁移到CPU上

jbd2/sda-18 为文件系统提供日志功能,保证数据的完整性

pdflush 内存中的脏页,写入磁盘

今天的案例是利用Nginx,模拟相关的请求

图片

我们分别运行两个Docker应用

然后进行访问Nginx的端口,确认Nginx的启动

图片

接下来,运行hPing3命令,模拟Nginx客户端

# -S参数表示设置TCP协议的SYN(同步序列号),-p表示目的端口为80

# -i u10表示每隔10微秒发送一个网络帧

# 注:如果你在实践过程中现象不明显,可以尝试把10调小,比如调成5甚至1

$ hping3 -S -p 80 -i u10 192.168.0.30

在ping命令开启后,我们查看对应的终端top

top命令获取到CPU的使用情况

$ top

top – 08:31:43 up 17 min,  1 user,  load average: 0.00, 0.00, 0.02

Tasks: 128 total,   1 running,  69 sleeping,   0 stopped,   0 zombie

%Cpu0  :  0.3 us,  0.3 sy,  0.0 ni, 66.8 id,  0.3 wa,  0.0 hi, 32.4 si,  0.0 st

%Cpu1  :  0.0 us,  0.3 sy,  0.0 ni, 65.2 id,  0.0 wa,  0.0 hi, 34.5 si,  0.0 st

KiB Mem :  8167040 total,  7234236 free,   358976 used,   573828 buff/cache

KiB Swap:        0 total,        0 free,        0 used.  7560460 avail Mem

PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND

9 root      20   0       0      0      0 S   7.0  0.0   0:00.48 ksoftirqd/0

18 root      20   0       0      0      0 S   6.9  0.0   0:00.56 ksoftirqd/1

2489 root      20   0  876896  38408  21520 S   0.3  0.5   0:01.50 docker-containe

3008 root      20   0   44536   3936   3304 R   0.3  0.0   0:00.09 top

1 root      20   0   78116   9000   6432 S   0.0  0.1   0:11.77 systemd

top中输出显示,两个CPU的软终端已经超过30%,而CPU使用率最高的进程,就是ksoftirqd进程

由此可以得出是网络收发导致的CPU使用率升高

对于这个内核线程,如何观察其行为呢?

如果使用pstack,或者通过/proc系统进行观测的话,效果都不是很好

那么如何观察内核线程ksoftirqd行为呢?

对于内核线程,可以考虑使用内核相关的性能工具,比如perf,试着分析一下进程号为9的ksoftirqd

在终端一中,执行如下的perf record命令,制定进程号为9,方便记录ksoftirqd的行为

# 采样30s后退出

$ perf record -a -g -p 9 — sleep 30

在之后,就可以执行perf report进行查看汇总

图片

ksoftirqd中调用栈如下

net_rx_action和netif_receive_skb 表示是接受网络包

br_handle_frame 网络的网桥经过

br_nf_pre_routing 表示网桥已经经过了netfilter的PREROUTING,这里说明有DNAT的发生

br_pass_frame_up,网桥处理之后,交给桥接的其他网卡进行处理

除此外,除了perf之外,还有这火焰图来进行汇总数据的这一种展示方式

图片

在这个图上,横轴和纵轴是不一致的

横轴表示采样数和采样比例,一个函数占用的横轴越宽,代表执行时间越长

纵轴是调用栈,从下往上逐个展开函数,下面的函数是上面的函数的父函数

至于颜色,则没有任何的特殊含义

而且在火焰图的内部,也有着不同目标,不同性能的分析

on-CPU: CPU繁忙情况

off-CPU: CPU等待IO,锁等各种资源的阻塞情况

内存火焰图,内存分配和释放情况

热/冷火焰图,将on-CPU和off-CPU结合一下展示

差分火焰图,红色表示增长,蓝色表示衰减,方便对比

进行分析的话,需要先生成火焰图

所以我们需要一些能从perf record中生成火焰图的工具,

$ git clone https://github.com/brendangregg/FlameGraph

$ cd FlameGraph

这样,我们需要先执行perf script ,将record转换为可读的采样

执行stackcollapse-perf.pl脚本,合并调用栈

执行flamegraph.pl脚本,生成火焰图

在Linux中,可以使用管道,简化三个步骤的执行

$ perf script -i /root/perf.data | ./stackcollapse-perf.pl –all |  ./flamegraph.pl > ksoftirqd.svg

然后打开浏览器,查看火焰图

那么,我们需要查看中间这一团最大的火

从下往上看,可以看出

还是net_rx_action – netif_receive_skb 到 钩子函数 到网桥

之后到ip_forward之后的,网络包进行发送

这就是利用火焰图,查看整体网络调用的详情

火焰图的作用中,包含去分析Nginx MySQL等场景性能问题

发表评论

邮箱地址不会被公开。 必填项已用*标注