irqbalance项目的主页在这里
irqbalance用于优化中断分配,它会自动收集系统数据以分析使用模式,并依据系统负载状况将工作状态置于 Performance mode 或 Power-save mode。处于Performance mode 时,irqbalance 会将中断尽可能均匀地分发给各个 CPU core,以充分利用 CPU 多核,提升性能。
处于Power-save mode 时,irqbalance 会将中断集中分配给第一个 CPU,以保证其它空闲 CPU 的睡眠时间,降低能耗。
在RHEL发行版里这个守护程序默认是开机启用的,那如何确认它的状态呢?
# service irqbalance status
irqbalance (pid PID) is running…
然后在实践中,我们的专用的应用程序通常是绑定在特定的CPU上的,所以其实不可不需要它。如果已经被打开了,我们可以用下面的命令关闭它:
# service irqbalance stop
Stopping irqbalance: [ OK ]
或者干脆取消开机启动:
# chkconfig irqbalance off
下面我们来分析下这个irqbalance的工作原理,好准确的知道什么时候该用它,什么时候不用它。
既然irqbalance用于优化中断分配,首先我们从中断讲起,文章很长,深吸一口气,来吧!
SMP IRQ Affinity 相关东西可以参见 这篇文章
摘抄重点:
SMP affinity is controlled by manipulating files in the /proc/irq/ directory.
In /proc/irq/ are directories that correspond to the IRQs present on your
system (not all IRQs may be available). In each of these directories is
the “smp_affinity” file, and this is where we will work our magic.
说白了就是往/proc/irq/N/smp_affinity文件写入你希望的亲缘的CPU的mask码! 关于如何手工设置中断亲缘性,请参见我之前的博文: 这里 这里
接着普及下概念,我们再来看下CPU的拓扑结构,首先看下Intel CPU的各个部件之间的关系:

一个NUMA node包括一个或者多个Socket,以及与之相连的local memory。一个多核的Socket有多个Core。如果CPU支持HT,OS还会把这个Core看成 2个Logical Processor。
Read more…
随着PCI-E SSD卡的普及,很多高性能的服务器都用上了如fusionio这样的设备来提升IO的性能,这样会带来一些问题。 这些高速的IO设备在运作的时候会产生大量的中断来通知IO的完成,全速运转的系统上中断达到14000irqs/sec 如图:

而中断是默认摊到所有的CPU:
#cat /proc/irq/1/smp_affinity
ffffffff
在实践中来看会落在最繁忙的0核心上,这样就会给性能雪上加霜,效果如下:
cat /proc/interrupts |grep fct
144: 39913474 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 IR-PCI-MSI-edge iodrive-fct0
145: 44976079 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 IR-PCI-MSI-edge iodrive-fct1
中断144,145属于iodrive-fct高速设备的,都落在了0号核心上。
对于大多数的高性能服务器通常都有16-32个核心,越靠后面的核心越闲,那为什么我们不把中断移到后面的核心,让核心0解放出来多做其他的事情呢?毕竟由于历史原因,很多东西还是在核心0上做的,减负!
这个问题的核心就是要设置/proc/N/145/smp_affinity的CPU掩码, 手工做比较麻烦。
好了,脚本来了:
# cat set_fio_affinity.sh
#!/bin/bash
set_affinity()
{
MASK_TMP=$((1<<(`expr $VEC + $CORE`)))
MASK=`printf "%X" $MASK_TMP`
printf "%s mask=%s for /proc/irq/%d/smp_affinity\n" $DEV$VEC $MASK $IRQ
printf "%s" $MASK > /proc/irq/$IRQ/smp_affinity
}
if [ $# -ne 1 ] ; then
echo "usage:"
echo " $0 core "
exit
fi
CORE=$1
DEV="iodrive-fct"
MAX=`grep -i $DEV /proc/interrupts | wc -l`
if [ "$MAX" == "0" ] ; then
echo no $DIR vectors found on $DEV
exit
fi
for VEC in `seq 0 1 $MAX`
do
for IRQ in `cat /proc/interrupts | grep -i $DEV$VEC|cut -d: -f1| sed "s/ //g"`
do
set_affinity
done
done
# ./set_fio_affinity.sh 30
iodrive-fct0 mask=40000000 for /proc/irq/144/smp_affinity
iodrive-fct1 mask=80000000 for /proc/irq/145/smp_affinity
再cat /proc/interrupts看下实践效果就可以看到后面的核心已经有中断了,而且0号核心上的数字没变!

# perf top –cpu=31
也验证了这一点:

另外一姐妹篇 “MYSQL数据库网卡软中断不平衡问题及解决方案” 参见 这里!
祝玩的开心!
Recent Comments