CPU资源调优

RH442 - 性能调优学习笔记(七)_笔记

IRQ 叫中断号,操作系统之所以能够跟设备打交道,其实就是依赖于中断号实现,每个设备都有中断号。

在以前还在使用拨号上网的时代,那么时候经常使用计算机的人可能遇到的一个经典的案例就是,当你正在拨号上网的时候,同时再使用打印机,打印出来的文件乱码, 或者已经拨号连接上了, 这个时候使用打印机就会造成断网。这通常是由于硬件的中断号冲突导致的,解决方案是开机进入BIOS 手动调整其中一个设备的中断号。如今之所以几乎没有这样的故障出现,是因为所有硬件的中断号是动态分配的,不是在bios 里面写固定的。

对于CPU 而言,进程需要分配CPU 资源,设备也需要分配CPU 资源。

系统中有一个文件:

cat /etc/interrupts
  • 1.

可以查看到系统中所有的中断使用的情况。

RH442 - 性能调优学习笔记(七)_CPU调优_02

第一列的数字是中断号,最后一列是设备,中间是每一个CPU 给设备分配的资源。

以网卡为例:

cat /proc/interrupts | grep ens
  • 1.

RH442 - 性能调优学习笔记(七)_笔记_03

系统给ens160 这块网卡分配了5 个队列,其中4 个是发送接收队列,1 个是事件管理队列。

这个看起来有点复杂了, 换RHEL 6 的系统演示:

RH442 - 性能调优学习笔记(七)_RH442_04

系统eth 0 这块网卡,中断号是19

cd /proc/irq
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_05

这个目录里面有很多中断号,每一个中断号对应一个设备。

刚刚看到的eth0 的中断号是19,进入到对应的目录里面来:

cd /proc/irq/19/
  • 1.

RH442 - 性能调优学习笔记(七)_笔记_06

RH442 - 性能调优学习笔记(七)_笔记_07

现在,这个文件内容最后有一个f,代表cpu mask,什么意思呢?

watch -n 1 -x cat /proc/interrupts | grep eth
  • 1.

RH442 - 性能调优学习笔记(七)_笔记_08

现在有外部主机ping 这块网卡,之前有说道,第一列显示的是中断号,第二列、第三列、第四列分别显示的是CPU0、CPU1、CPU2 ... ,现在只有CPU 0那一列有数字,而且数字还在递增,说明eth 0 网卡接收到外部主机的ping 流量是CPU 0 在处理。

 回到cpu mask,那个f,转换成十进制数,就是2^0=0,所以是CPU0,如果是CPU1,就是2^1,CPU2是2^2,CPU3是2^3,以此类推...

echo 00000002 > smp_affinity
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_09

现在再来观察:

RH442 - 性能调优学习笔记(七)_CPU调优_10

是CPU1在处理。

同样地:

echo 00000004 > smp_affinity
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_11

echo 00000008 > smp_affinity
  • 1.

RH442 - 性能调优学习笔记(七)_笔记_12

如果我想让CPU0和CPU1一起来处理eth0 网卡的流量,这样:

echo 00000003 > smp_affinity
  • 1.

RH442 - 性能调优学习笔记(七)_RH442_13

在网卡流量较小的时候,仍然只会分配到一个CPU上工作,遇到并发流量时,才会分配到多个CPU处理。

那么,默认值的f,就表示分配到所有的cpu 处理,这个叫irq 的均衡。

RH442 - 性能调优学习笔记(七)_笔记_14

除了irq 中断,还有cpu 中断,它决定了一个进程运行在哪一个cpu 上

RH442 - 性能调优学习笔记(七)_笔记_15

默认情况下,一个进程也会均衡地运行在各个cpu 上,我们可以手动指定一个进程固定运行在某一个cpu 上。

ps -axo %cpu,%mem,%pid,comm,psr | more
  • 1.

RH442 - 性能调优学习笔记(七)_RH442_16

psr 的参数是用来显示一个进程运行在哪个cpu 上。

下面做一个小实验:

cp -r /usr /etc /tmp &
watch -n 1 -x ps -axo %cpu,%mem,%pid,comm,psr | grep -w cp
  • 1.
  • 2.

RH442 - 性能调优学习笔记(七)_RH442_17

RH442 - 性能调优学习笔记(七)_RH442_18

RH442 - 性能调优学习笔记(七)_RH442_19

RH442 - 性能调优学习笔记(七)_笔记_20

一个程序繁忙的时候,它会运行在不同的cpu 上。

再来测试一个:

md5sum /dev/zero &
watch -n 1 -x ps -axo %cpu,%mem,%pid,comm,psr | grep -w md5sum
  • 1.
  • 2.

RH442 - 性能调优学习笔记(七)_RH442_21

这个程序则只会在cpu2 上运行。

为什么有些程序会在不同的cpu 之间跑动呢?

一个cpu 同时只能处理一个程序,md5sum 本身就是一个程序, 而cp 则涉及循环,本质上是多个程序。

那么我们如何把那些不会分散在不同cpu上运行的程序分散,把分散在不同cpu上运行的程序固定呢?

RH442 - 性能调优学习笔记(七)_笔记_22

RH442 - 性能调优学习笔记(七)_RH442_23

taskset -p 11216
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_24

现在这个mask 值是f,表示这个进程可以在所有的cpu 上运行。

指定这个进程仅在cpu1上运行,那么mask 值应为2^1=2:

taskset -p 2 11216
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_25

指定这个进程仅在cpu1上运行,那么mask 值应为2^2=4:

taskset -p 4 11216
  • 1.

RH442 - 性能调优学习笔记(七)_笔记_26

RH442 - 性能调优学习笔记(七)_笔记_27

如果想要指定这个进程仅在cpu0 和cpu1 上运行:

taskset -p 3 11216
  • 1.

通过设置这个mask 值就可以根据自己的需要指定了。

那么这样调节有什么意义呢?

默认情况下,进程均衡运行在各个cpu 上,并且会在不同的cpu 上进行移动,优点是提升吞吐量,缺点是会导致cpu cache miss

为了提升进程的cache hit rate 缓存命中率,我们可以把进程绑定到指定的cpu 上运行。

RH442 - 性能调优学习笔记(七)_CPU调优_28

RH442 - 性能调优学习笔记(七)_CPU调优_29

接下来做一个实验:

mkdir /cpuset
  • 1.

系统中有一个特殊的文件系统叫cpuset:

cat /proc/filesystems
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_30

mount -t cpuset nodev /cpuset
cd /cpuset
  • 1.
  • 2.

RH442 - 性能调优学习笔记(七)_RH442_31

这里面包含了所有的cpuset 资源,包括cpus、mems、tasks 等等...

可以理解为我们现在所在的工作目录就是根cpuset

RH442 - 性能调优学习笔记(七)_CPU调优_32

RH442 - 性能调优学习笔记(七)_笔记_33

可以看到vsftpd 这个进程在tasks 里面可以找到。

建子文件夹:

mkdir web
mkdir database
  • 1.
  • 2.

RH442 - 性能调优学习笔记(七)_RH442_34

RH442 - 性能调优学习笔记(七)_RH442_35

进入web 目录,里面已经有很多内容了,但是它没有资源,database 也一样

echo 1 > cpuset.cpus
  • 1.

RH442 - 性能调优学习笔记(七)_笔记_36

把1 号处理器绑定给这个cpuset

因为这台机器不支持NUMA,所以只有一个memory zone

echo 0 > cpuset.mems
  • 1.

RH442 - 性能调优学习笔记(七)_RH442_37

把0 号memory zone 绑定给这个cpuset

把任务附加给cpuset:

echo 1279 > tasks
  • 1.

RH442 - 性能调优学习笔记(七)_RH442_38

此时,这个进程就会运行在这个cpuset 里面,它就得到了1号处理器和0号memory zone

可以用以下命令来验证:

watch -n 1 -x ps -axo %cpu,%mem,comm,pid,psr | grep vsftpd
  • 1.

但是,这里要注意,vsftpd 服务必须处于运行状态才可以看到效果,如果处于休眠状态则不生效。

如果没有手动挂载cpuset,默认挂载到/sys/fs/cgroup:

RH442 - 性能调优学习笔记(七)_笔记_39

如果你不想用自定义的cpuset,不可以直接用rm -rf 这样的命令来删,这是内存中的数据,需要用rmdir 来删除:

cd /sys/fs/cgroup/cpuset
rmdir database
rmdir web
  • 1.
  • 2.
  • 3.

RH442 - 性能调优学习笔记(七)_CPU调优_40

提示设备忙

我们把目录里面的资源解除再重试

RH442 - 性能调优学习笔记(七)_CPU调优_41

RH442 - 性能调优学习笔记(七)_笔记_42

这样就可以删除了。

如果要想让处于休眠状态的vsftpd服务绑定cpuset 生效,需要下面这样做:

cd /usr/local/bin
vim cpuset.sh
  • 1.
  • 2.

RH442 - 性能调优学习笔记(七)_RH442_43

# chmod u+x cpuset.sh
# cd /etc/systemd/system/
# mkdir vsftpd.service.d
# cd vsftpd.service.d/
# vim 01-cpuset.conf
[Service]
ExecStartPost=/usr/local/bin/cpuset.sh
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.

这行代码表示会在服务启动完成后执行这个脚本。

systemctl daemon-reload
systemctl restart vsftpd
  • 1.
  • 2.

验证结果:

ps axo %cpu,%mem,pid,comm,psr | grep ftp
  • 1.

RH442 - 性能调优学习笔记(七)_RH442_44

RH442 - 性能调优学习笔记(七)_CPU调优_45

这个参数,表示是否独占cpu 资源,默认是0,表示关闭,如果设为1,表示打开,那么其它cpuset 就不能设置与我相同的cpu 资源了,但这是对于子cpuset 而言,根cpuset 不会受影响。

那么如果我想查看某一个进程运行在哪个cpuset 上,下面这样操作:

cd /proc/1/cpuset
  • 1.

RH442 - 性能调优学习笔记(七)_CPU调优_46

比如说上面这个ID 为1 的进程,其实也就是systemd 进程,运行在根cpuset 上。

RH442 - 性能调优学习笔记(七)_RH442_47

vsftpd 运行在web cpuset 上。


持续更新中...