Thursday, May 10, 2012

[Linux]优化网卡性能

参考
Tuning 10Gb network cards on Linux
Setting IRQ Affinity for Red Hat Summit 10G Ethernet Tuning
1 设定网卡IRQ affinity.
设置IRQ affinity就是将同一设备的IRQ绑定到同一个(组)CPU上.
比如你可以通过mpstat这个命令来查看当前CPU处理IRQ的分配. 比如查看所有CPU, 每隔5秒刷新一次:
$ mpstat -P ALL 5
如果要改变某个IRQ的CPU affinity, 可以通过写相关IRQ/proc/irq/路径来实现. 比如
$ echo 80 > /proc/irq/177/smp_affinity
这个命令将IRQ 177的affinity掩码改为0x80
一个实例:
eth5为一个10G网卡,所以系统会对这块网卡产生N个TxRx队列,N为core数目.所以我当前机器上有24个core,所以有24个队列.我希望将每个队列的mask均为0x00ffffff,也就是所有的core都可能处理eth5产生的IRQ.有时候我们希望讲同一个设备的IRQ绑定在同一个(组)core上,从而提高cache的性能. 这里附上一个寻找并显示某个网卡设备(比如eth0, eth5)相关的IRQ以及其smp_affinity mask的脚本
#!/usr/bin/python

import os
import sys 

names = []

args = sys.argv[1:]
while args:
    names.append(args[0])
    args = args[1:]

for dir_name in os.listdir('/proc/irq/'):
    if not os.path.isdir('/proc/irq/%s' % dir_name):
        continue
    for file_name in os.listdir('/proc/irq/%s' % dir_name):
        found = False
        for idx, name in enumerate(names):
            if file_name.startswith(name):
                found = True
        if not found: continue
        path = '/proc/irq/%s/smp_affinity' % dir_name
        print path, file_name
        print 'mask = %s' % (open(path).read().strip())
        break
运行这个脚本:
$ sudo ./get_smp_affinity.py eth5
/proc/irq/127/smp_affinity eth5:lsc
mask = 00ffffff
/proc/irq/126/smp_affinity eth5-TxRx-23
mask = 00ffffff
...
...
/proc/irq/103/smp_affinity eth5-TxRx-0
mask = 00ffffff
这里我还有一篇post介绍如何在C当中设定CPU affinity.[Linux]使用C设置线程的CPU affinity. 在一个试验中, 我用如上方法把一个24-core的CPU中core0到core5设定为处理10Gb网卡的IRQ, 而把我的程序线程绑定在core6以上,从而取得了最大的throughput.

2 Ethernet Interrupt coalescing
这篇"Interrupt coalescing"解释了什么是Interrupt coalescing. ethtool 是用来显示以及修改网卡的设定的工具. ethtool -c选项可以用来显示网卡的Interrupt coalescing参数. 比如要显示eth0的参数:
sudo ethtool -c eth0
Coalesce parameters for eth0:
Adaptive RX: off  TX: off
stats-block-usecs: 999936
sample-interval: 0
pkt-rate-low: 0
pkt-rate-high: 0

rx-usecs: 18
rx-frames: 12
rx-usecs-irq: 18
rx-frames-irq: 2

tx-usecs: 80
tx-frames: 20
tx-usecs-irq: 18
tx-frames-irq: 2

rx-usecs-low: 0
rx-frame-low: 0
tx-usecs-low: 0
tx-frame-low: 0

rx-usecs-high: 0
rx-frame-high: 0
tx-usecs-high: 0
tx-frame-high: 0
参数解释
rx-usecs和rx-frames控制每一个RX DMA channel的RX interrupt速率. 每当累计接收到rx-frames这么多个,或者rx-usecs这么长时间过后, 一个RX interrupt就会被产生. 对于low latency要求的application, 尽量将rx-usecs设置小. 而对于bulk traffic, 设置大.
rx-frames-irq 控制最多一个RX interrupt可以处理多少个RX packets
将eth0的rx queue的timer设为1000 us
sudo ethtool -C eth0 rx-usecs 1000

3 TCP/UDP parameter tuning
(待续...)

No comments: