PCI-E SSD卡中断配置问题
随着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掩码, 手工做比较麻烦。
好了,脚本来了:
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 |
MAX=` grep -i $DEV /proc/interrupts | wc -l` |
if [ "$MAX" == "0" ] ; then |
echo no $DIR vectors found on $DEV |
for VEC in ` seq 0 1 $MAX` |
for IRQ in ` cat /proc/interrupts | grep -i $DEV$VEC| cut -d: -f1| sed "s/ //g" ` |
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数据库网卡软中断不平衡问题及解决方案” 参见 这里!
祝玩的开心!
http://www.freepatentsonline.com/8312195.html 当心专利侵权。。。
为啥要写脚本设置这个? 难道不是 echo一下就改好了吗?
Yu Feng Reply:
January 25th, 2013 at 3:31 pm
细节是魔鬼!
tomwang1013 Reply:
November 12th, 2014 at 11:01 am
试了下,用echo直接改不会成功,马上又被恢复了,不知道咋回事,博主能回答下吗?
请问一下,一开始的时候掩码全是f,应该代表着“分摊到所有CPU“,为什么实际情况确是只分配到了CPU0呀?
Yu Feng Reply:
November 22nd, 2013 at 5:17 pm
恩,这个问题问的好,我也在想这个问题。
tomwang1013 Reply:
November 12th, 2014 at 12:17 pm
想出结果了吗?最近也碰到过更改/proc/irq/N/smp_affinity没生效的情况,不知从何查起
还要关掉irqbalance吧,不然该服务会让irq在不同的CPU上跑
oprofile的功能和perf类似,但感觉perf更方便一些。除了使用上的方便之外,不知道这两者有什么区别?