核孤立和绑定是一种有效的性能优化手段,能够有效降低关键线程或进程时延,提升运行稳定性。本文前两节描述如何尽量将其他用户或内核线程隔离在指定核心之外,第三节介绍如何将时延敏感进程绑定到指定隔离好的孤立核心上。
1 Core Isolation
1.1 使用tuned实现核孤立
redhat官方推荐使用tuned及其tuned-profiles-realtime模式来做核孤立
- 安装:yum install tuned tuned-profiles-realtime
- 修改/etc/tuned/realtime-variables.conf文件,配置isolated_cores=cpulist,cpulist使用逗号隔开,可是cpu标号或者标号范围,如isolated_cores=0-3,5,7。一旦设置了isolated_cores,任何用户空间线程都不会被分配在这些CPU核心上。
- 使用tuned-adm来激活tuned的配置:tuned-adm profile realtime
- 重启:reboot
1.2 tuna工具
tuna可以方便实现核孤立,修改IRQ,修改线程的调度策略及优先度信息,详见参考[REF.5]
tuna --cpus=cpu_list --isolate
1.3 直接修改grub实现核孤立
将列表中的CPU从内核SMP平衡和调度算法中剔除,该核心不能执行任何非绑定的内核线程。
提出后并不是绝对不能再使用该CPU的,操作系统仍然可以强制指定特定的进程使用哪个CPU(可以通过taskset来做到)。具体的修改方法是在/boot/grub/grub.conf的kernel列最末尾加上isolcpus=x,y,… (代表将CPUx CPUy隔离),修改后使其grub配置生效后重启。
检查是否生效
查看grub参数:cat /proc/cmdline | grep isolcpus
查看进程当前运行在哪个CPU上:taskset -p [pid]
2 解决中断Interrupt
默认情况下,Linux的中断响应会被平均分配到所有CPU核心上,这样势必会发生写新的数据和指令缓存,而且还会与CPU核心上原来存在的进程产生冲突,影响低延迟线程上的处理时间。
为了解决这个问题,可以将中断(或进程)绑定到指定的CPU核心上,让终端对于低延迟线程的影响尽可能的小;另一方面,绑定的终端(或进程)所需要的代码和数据结构就有更高的可能性位于本地CPU的数据和指令缓存内,而不必进行新的写缓存,从而提高中断响应(或进程)的处理速度。此外,将某一个进程及其相关的中断绑定在同一个CPU核心上,使它们共享缓存线路,可以提高程序性能。还有,将彼此不相关的中断与进程绑定到不同的CPU核心上,可以避免冲突,也可以提高程序性能。
管理中断的初衷是当CPU空闲时即处于IDLE状态时针对CPU的节能考虑,增加了nohz参数,后面慢慢演进可用于针对抖动和时延敏感的CPU优化。
通过配置内核参数可以避免未绑定的定时器的中断,定时器的回调,工作队列和其他内核线程影响时延敏感线程,然而还有一些硬件IRQ需要通过配置irqbalance来做隔离,下面分别对这两个方面进行介绍。
2.1 配置内核参数避免中断
nohz_full
nohz_full指定哪些CPU进入无滴答状态。当指定CPU上只运行一个任务或者运行实时任务时,关掉该CPU的周期tick,内核不会向该CPU上发送计时器信号,减少服务终端和上下文切换。开启nohz_full的同时需要开启nohz,开启nohz后nohz_full这个参数才会生效。
cpu lists格式见[REF.9]
遇到的问题:当设置nohz和nohz_full后,即使cpu处于idle状态或者运行实时任务,仍然会有周期中断(tick)。这是因为CPU从idle状态退出时,会无条件的重启tick,如果这个此时任务队列只有一个任务或者这个任务具有最高优先级,则这个tick只trigger一次,但是这个tick仍然会对正在运行的进程造成干扰。fixed patch(华为藏龙卧虎,牛批):[tip: timers/nohz] tick/nohz: Conditionally restart tick on idle exit - tip-bot2 for Yunfeng Ye
rcu_nocbs
RCU(Read-copy Update)是一个高性能的锁机制,在读多写少的情况下,对于被RCU保护的共享数据,读者不需要获得锁就可以访问(速度快)。但是对于写操作,它首先copy一个副本,然后对副本进行修改,最后使用回调机制在适当的时候将原数据指针指向被修改的数据,因此写速度很慢。
每个CPU上都有一个rcuc的内核线程,用于处理回调工作。使用rcu_nocbs=cpulist这个配置可以指定某些CPU是无回调的,当需要使用回调机制时,将工作转移到其他cpu。若设置了nohz_full会自动做rcu的回调隔离,不用再单独配置。
2.2 配置irqblance避免中断
中断平衡守护进程(irqbalance daemon)会周期性地将中断平均地公平地分配给各个CPU核心,它默认是开启的。一种方法我们可以直接关闭irqblance,中断就不会自动分配到各个核心;另一种方法就是自定义中断平衡策略,可以将时延敏感核心从策略中剔除也就是不接收中断,也可以设置中断的亲和性使中断不会分配到时延敏感核心中,下面逐一介绍。
关闭irqblance
将这个守护进程关闭就可以将中断响应都由CPU0核心处理。
查看守护进程的运行状态:systemctl status irqbalance
关闭守护进程:systemctl stop irqbalance
取消进程,使其开机不会重启:systemctl disable irqbalance
指定CPU脱离irqblance
我们可以通过修改 /etc/sysconfig/irqbalance 配置文件,将指定的CPU核心从中断平衡守护进程的列表中脱离出来,即守护进程不会再将中断分配给这些CPU核心。
打开/etc/sysconfig/irqbalance文件,找到“#IRQBALANCE_BANNED_CPUS=”位置,将注释取消,然后在等号后面填写CPU十六进制掩码,比如
IRQBALANCE_BANNED_CPUS=0000ff00
这里的掩码最多可以有64位,如果系统具有的核心数超过32个,则可以在等号后面添加两个32位掩码,并用逗号隔开,例如
IRQBALANCE_BANNED_CPUS=00000001,0000ff00
就是将8~15和33这9个核心隔离了。
设置中断的CPU亲和性
设置中断的CPU亲和性(affinity),就是让该中断只在指定CPU核心上进行响应,即中断绑定。
通过/proc/interrupts文件查看一下各种中断的响应情况,第一列显示的中断ID号,CPUn列显示的是该中断在第n个CPU核心上的响应次数,倒数第二列是中断类型,最后一列是描述。
利用echo命令将cpu掩码写入/proc/irq /中断ID/smp_affinity文件中,即可实现修改某一中断的CPU亲和性。例如:
echo 0x0004 > /proc/irq/170/smp_affinity
就可以将ID为170的中断的响应绑定到CPU3核心上。当该中断下一次发生时,再查看/proc/interrupts里面的响应数量,会发现CPU3核心的响应次数增加了,而其它核心的响应次数没有改变。
内核官方说明见[REF.10]
3 Core Bind
设置CPU亲和性指定我们的需要绑核的工作进程到前面已配置的孤立核心,
3.1 代码绑核
线程绑核
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);
进程绑核
int sched_setaffinity(pid_t pid, size_t cpusetsize, const cpu_set_t *mask);
代码示例见[REF.1]和[REF.2]。
3.2 命令行绑核
taskset
查看进程当前运行在哪个CPU上:taskset -p [pid]
指定进程运行在第二个CPU(CPU1)上:taskset -pc 1 进程号
在启动程序时绑定CPU:taskset -c 1 ./test.sh&
Numatcl
安装:yum -y install numactl
绑定CPU:numactl -C 1 ./test.sh&
cpuset
还可以使用cpusets/cgroups,见[REF.12]
REF
- CPU Affinity | Linux Journal
- c - Whole one core dedicated to single process - Stack Overflow
- 3.13. Isolating CPUs Using tuned-profiles-realtime Red Hat Enterprise Linux for Real Time 7 | Red Hat Customer Portal
- 6.3. Configuration Suggestions Red Hat Enterprise Linux 7 | Red Hat Customer Portal
- Chapter 4. Tuna Red Hat Enterprise Linux 7 | Red Hat Customer Portal
- pthread_setaffinity_np(3) - Linux manual page (man7.org)
- sched_setaffinity(2) - Linux manual page (man7.org)
- CPU_SET(3) - Linux manual page (man7.org)
- The kernel’s command-line parameters — The Linux Kernel documentation
- https://www.kernel.org/doc/Documentation/IRQ-affinity.txt
- CPU Isolation - Introduction – by SUSE Labs (part 1) | SUSE Communities
- Control Groups — The Linux Kernel documentation
版权归原作者 littlepeanut.top 所有, 如有侵权,请联系我们删除。