1.0 简介
该指南旨在为Linux环境中使用Intel x710/xl710系列网卡提供调优指导,以获取最佳的网络性能。该指南着眼于可能带来网络性能提升的硬件、驱动和操作系统环境和设置等方面。值得注意的是,网络性能会受到任何外界因素的影响,该指南只涉及那些最普遍和影响最显著的部分。
2.0 预先检查项
2.1 升级Driver/Firmware版本
使用命令“ethtool -i ethX”检查driver/firmware版本。
2.2 参考驱动中的README
检查有哪些已知问题以及从i40e驱动源码包中的README中获取最新的配置指令。
2.3 确认x8 PCIe插槽
有些PCIe x8插槽被配置成x4插槽使用。在外接2端口和4端口设备时不能使用全部的带宽。另外,如果你将一个支持PCIe 3.0的网卡插入PCIe 2.x插槽,同样也使用不了全部的带宽。设备驱动会识别此种情形并在system日志中记录如下信息:
PCI-Express bandwidth available for this card is not sufficient for optimal performance. For optimal performance a x8 PCI-Express slot is required.
如果出现该信息,将支持PCIe 3.0的网卡插入PCIe v3.0 x8插槽即可。
2.4 检查系统硬件能力
10Gb/s和40Gb/s的以太网对CPU和系统均有最低配置需求。通常来说,对一个平台而言,一个服务器专用的处理器和最佳的内存配置是最低要求,但依据实际的负载也会有所不同。所有的内存通道都应被填充并且BIOS设置中也要打开内存性能模式。确保你的CPU和内存配置能够支持实际负载所需的网络性能。
XL710是一个40GbE控制器。如果2个40GbE网卡使用该控制器并不会如期获得2 x 40GbE而是一个带有处于激活状态的备用port的1 x 40GbE。当尝试将2个port都用于line-rate流量时,内部开关将会饱和并且2个port的综合带宽将限制在50Gb/s。
2.4.1 内核启动参数
如果在BIOS中开启了为Directed I/O而设计的虚拟化技术,为获取最佳的主机网络性能,Intel建议将IOMMU设置为pass-through模式。这将在主机网络流量中减少DMA的开销,使得在开启VMs的同时仍能使用Intel VT-d技术还来的益处。完成该模式的设置只需要在内核启动参数中增加“iommu=pt”即可。
3.0 性能基准测量方法及调优方法论
3.1 网络性能基准
在开始调优之前,为网络性能制定一个设计良好的基准测量方法是很重要的。通常来说,在为你的应用或负载制定性能初始测量方法的同时,使用标准的网络性能基准保证网络设备工作良好是一个好的建议。
对于单机系统的优化,netperf或者iperf和NetPIPE这些完全免费开源的工具可以用于压力测试链接或诊断性能相关问题。Netperf在吞吐量和时延测试方面都很强大。NetPIPE是一个特定于时延的工具,但可以集成在任何类型的环境中。
netperf返回的时延数据中TCP_RR的单位为transactions/sec。这是一个round-trip数值。因此,可以使用下述公式计算单向时延:
Latency(usec) = (1/2) / [Transactions/sec] * 1000000
3.2 调优方法论
一次只聚焦一个调优项的修改,这样就可以得知每次的修改所带来的影响。在调优过程中越有条不紊的测试,就越容易定位和跟踪到引发性能瓶颈的根本原因。
4.0 i40e驱动设置调优
4.1 IRQ亲和性
设置IRQ亲和性,即将不同网卡队列的中断绑定到不同的CPU核心,将会对性能产生巨大的影响,特别是在多线程吞吐量的测试中。
要设置IRQ的亲和性,首先先停止irqbalance服务,然后使用i40e源码包中的set_irq_affinity脚本或手动设置均可。
关闭用户态IRQ均衡器以开启队列绑定:
- systemctl关闭irqbalance
- systemctl停止irqbalance
使用i40e源码包中的set_irq_affinity脚本(推荐):
- 使用所有CPU核心:
[path-to-i40epackage]/scripts/set_irq_affinity -x all ethX
- 只使用本地NUMA节点中的CPU核心:
[path-to-i40epackage]/scripts/set_irq_affinity -x local ethX
- 你还可以选择某个范围内的CPU核心。避免使用CPU0,因为它用于timer任务。
[path-to-i40epackage]/scripts/set_irq_affinity 1-2 ethX
手动设置:
- 使用下列命令查找绑定到每个节点的处理器核心:
numactl --hardware
lscpu
- 查找每个处理器核心的bit掩码:
- 假设节点0有处理核心0-11:[1,2,4,8,10,20,40,80,100,200,400,800]
- 查找当前指定到port的IRQ:
grep ethX /proc/interrupts and note the IRQ values
For example, 181-192 for the 12 vectors loaded.
- 将SMP亲和性值写入相应的IRQ条目。要注意的是,需要为每个IRQ条目写入相应的亲和性值:
echo 1 > /proc/irq/181/smp_affinity
echo 2 > /proc/irq/181/smp_affinity
echo 4 > /proc/irq/181/smp_affinity
4.2 中断调控
默认情况下,自适应的中断调控功能是开启的,并且设计该功能的目的是在低CPU利用率和高性能之间提供一种平衡方法。然而,你可以根据实际情况手动调整中断相关配置。
0-235微秒的范围提供了每秒4310到250000次有效的中断。使用ethtool命令可以单独设置rx-usecs-high的值而不用考虑rx-usecs和tx-usecs,也不用考虑自适应中断调控算法。所依赖的底层硬件仅支持粒度为2微秒的间隔,所以不同的相邻数值可能对应到同一中断频率。
- 关闭自适应中断调控功能
ethtool -C ethX adaptive-rx off adaptive-tx off
- 开启自适应中断调控功能
ethtool -C ethX adaptive-rx on adaptive-tx on
对一般的调优来说,84us或~12000次中断每秒是一个不错的起始值。如果在有网络流量时观测到rx_dropped的值在增涨(使用ethtool -S ethX),那么有可能是CPU工作太慢导致网卡的ring buffer不够用于存放数据包或者中断频率太低。
- 将中断调控设置到固定的中断频率84us,大约12000中断每秒:
ethtool -C ethX adaptive-rx off adaptive-tx off rx-usecs 84 tx-usecs 84
如果没有将CPU利用率最大化,那么下一个尝试的值将是62us。这将使用更多的CPU,更快的服务于ring buffer,也就使用更少的buffer描述器了(ring size,ethtool -G)。
- 将中断调控设置到固定的中断频率62us,大约16000中断每秒:
ethtool -C ethX adaptive-rx off adaptive-tx off rx-usecs 62 tx-usecs 62
如果此时CPU利用率已达100%,那么不再建议继续调高中断频率。在某些特定的环境中,比如CPU消耗型的负载,你可能会增加us的值以释放更多的CPU给其他应用程序使用。
如果你需要低时延的性能或将CPU预留给网络处理,你可以完全关闭中断调控功能,这将使得中断将尽可能快地被触发。
- 关闭中断调控功能
ethtool -C ethX adaptive-rx off adaptive-tx off rx-usecs 0 tx-usecs 0
4.3 Ring Size
如果你通过命令ethtool -S ethX观察到rx_dropped的值非零,或者估量激活多队列时缓存的压力,你可以尝试修改ring size的值,默认值是512,而最大值为4096。
如果在当前的中断频率下,怀疑是缓存不够引起的丢包,你可以先尝试使用最大值,然后再尝试使用最小值,接下来就可以使用二分查找的方法尝试不同的值直至达到最优性能。
如果激活多队列的情况下怀疑缓存压力大,那么降低缓存空间会有助于提升Data Direct I/O操作效率。Intel推荐为每个队列设置ring size为128或256的同时,还提醒使用ethtool -C命令增加中断频率将可能避免rx_dropped值的增长。
- 将ring size设置为固定值
ethtool -G ethX rx 256 tx 256
4.4 Flow Control
协议栈2层的flow control可能会一定程度上影响TCP性能,针对大多数类型的负载,都建议关闭该功能。一个潜在的例外是并不会持续大久的突发流量。默认情况下,flow control是被关闭的。
开启flow control:
ethtool -A ethX off rx on tx on
关闭flow control:
ethtool -A ethX rx off tx off
你必须有一个支持flow control的链路层设备才能开启flow control。
5.0 系统调优(非特定于i40e)
5.1 BIOS设置
为虚拟化类型的负载开启Intel VT-d功能。
超线程技术(逻辑CPU)也可能会影响性能,分别为你的实际负载进行开启或关闭调优。
5.2 能耗管理
能耗管理也会对性能产生影响,特别是在低时延类型的负载环境中。如果性能比节省能耗拥有拥有更高的优先级,建议在限制能耗管理所带来的影响的前提下进行调优。在限制能耗管理方面有着多种不同的方法,通过操作系统工具,BIOS设置和内核启动参数。选择最适合你环境的方法。
5.2.1 C-state控制
将C-state限制在C0或C1状态以提高性能并且增加能源使用率。
动态调控C-state状态的方法之一是打开文件/dev/cpu_dma_latency并且写入允许的最大时延。一个名为cpudmalatency.c的小程序可以以命令行的方式完成该任务,该小程序可以从开源社区下载,然后编译和运行。接下来的示例中允许5us的唤醒时间,也即处于C1状态:
cpudmalatency 5 &
另外一个方法是在内核启动时设置C-state的最大限制:
intel_idle.max_cstates=1 (for Inter CPUs) or processor.max_cstates=1 (for non-Intel CPUs)
除此之外,还可以在内核启动命令行中加入以下命令以屏蔽任何C-state状态:
idle=poll
第3种方法是通过系统BIOS能耗管理设置,可能会有可用的性能配置文件。
类似turbostat或x86_energy_perf_policy这样的工具也可以用于检测或设置能耗管理相关的设置。
5.2.2 PCIe能耗管理
Active-State Power Management(ASPM)使得PCIe链路在不使用时处于低能耗状态。这将给PCIe上的网络设备带来更高的时延,所以建议对于时延敏感的负载关闭ASPM。
在内核启动命令行中加入以下选项以关闭ASPM:
pcie_aspm=off
5.2.3 CPU频率调控
CPU frequency scaling或CPU speed scaling是一种Linux能耗管理技术,该技术动态调整系统时钟频率以达到节省能源和减少发热的目的。与C-state类似,这将引起网络连接产生非预期的时延。
要关闭CPU frequency scaling,关闭CPU能耗管理服务,可以使用以下命令:
systemctl stop cpupower.service
systemctl disable cpupower.service
5.3 防火墙
防火墙也会对性能产生影响,特别是对时延相关的性能。如果不需要iptables/firewalld时,可以关闭。
5.4 应用程序设置
通常来说,单一线程(对应单个网络队列)是不能达到最大带宽的。可能的话,调优应用程序使用的线程数。
5.5 内核版本
大多数现代内核都已经为性能做了充分合理的优化,但是依据你的实际使用情况,升级内核可能会带来更好的性能。下载内核源码,在编译内核之前可以选择性地开启或关闭某些不用的特性。
5.6 操作系统/内核设置
查阅类似Red Hat Enterprise Linux Network Performance Tuning Guide这样的操作系统调优指南可以获得更多通用操作系统调优方面的想法。
在下表中已经罗列一些通用的参数可供调优。需要注意的是,这些只是建议的开始值,对它们的任何修改都可能会增加系统对资源的使用。虽然增加这些值可以帮助提升性能,但尝试不同的值使当前系统、负载和流量类型达到最优工作状态仍然是必须的。
如以下示例所示,可以使用sysctl命令配置内核参数:
sysctl -w net.core.rmem_default=524287
不带-w参数执行sysctl命令时将会显示配置的当前设置值:
Stack Setting |
Description |
net.core.rmem_default |
Default Receive Window Size |
net.core.wmem_default |
Default Transmit Window Size |
net.core.rmem_max |
Maximum Receive Window Size |
net.core.wmem_max |
Maximum Transmit Window Size |
net.core.optmem_max |
Maximum Option Memory Buffers |
net.core.netdev_max_backlog |
Backlog of unprocessed packets before kernel starts dropping |
net.ipv4.tcp_rmem |
Memory reserver for TCP read buffers |
net.ipv4.tcp_wmem |
Memory reserver for TCP send buffers |
6.0 性能故障排除
6.1 CPU利用率
当运行负载时检查每个CPU核心的利用率。值得注意的是,与整体CPU利用率相比,每个核心的利用率与性能关联更加紧密,因为它提供了关于每个网络队列的CPU利用率。如果你只运行了很少的几个处理网络流量的线程,那么你也只是使用了很少的CPU核心。然而,如果这些核心都处于100%,那么你的网络吞吐很可能受限于CPU利用率,此时需要进行下列2项操作:
- 如4.3节中所述对IRQ调控和ring size进行调优;
- 增加应用程序的线程数将CPU负载分摊到更多的核心上。如果所有的核心都处于100%,那么你的应用程序瓶颈受限于CPU而不是网络;
通常可以使用的工具有:
- top
按1键列出所有CPU核心并且检查哪些核心正在处理数据。着重关心利用率和哪些核心处于活动状态。
- mpstat
接下来的命令行示例已经在Red Hat Enterprise Linux 7.x上进行测试。它提供了每个CPU核心的利用率(查找并从100中减去空闲百分比)并用红色高亮显示利用率高于80%的核心。
mpstat -P ALL 1 1 | grep -v Average | tail -n +5 | head -n -1 | awk '{ print (100-$13)}' | egrep --color=always '[^\.][8-9][0-9][\.]?.*|^[8-9][0-9][\.]?.*|100|' | column
- perf top
定位CPU利用率耗费在哪些循环中。
6.2 i40e计数器
i40e驱动为使用ethtool -S ethX命令对网络接口进行debug和监控提供了一个很长的计数器列表。这将有助于在运行负载时观察网络接口相关的输出以及对比运行前后的值。
获取所有的i40e计数器的值:
ethtool -S ethX
仅观察所有非零的计数器:
watch -d (ethtool -S ethX) | egrep -v :\ 0 | column
可能需要关注的一些计数器:
rx_dropped:CPU没有及时从buffer中获取数据包。
port.rx_dropped:slot/memory/system工作频率不够快。
6.3 网络计数器
在运行负载前后执行netstat -s命令。
Netstat从系统中的所有网络设备中收集网络信息,所以结果有可能会受到非测试设备的影响。然而,netstat -s的输出仍然是Linux操作系统或内核方面性能问题的良好启示。查阅类似Red Hat Enterprise Linux Network Performance Tuning Guide这样的操作系统调优指南可以获得更多通用操作系统调优方面的想法。
6.4 系统日志
检查系统日志中的错误和告警信息(/var/log/messages,dmesg)。
7.0 通用性能场景下的建议
7.1 IP转发
- 升级内核
由于内核路由相关的源码在考虑到安全的前提下删除了路由缓存,一些最近发行的内核版本在路由性能方面有所下降。最近一些发行版之外的内核已经发布了一些patch,能够减少这些源码修改带来的性能方面的影响,这可能会提升一些性能。
- 关闭超线程(逻辑核)
- 修改内核启动参数
如非虚拟化需要,在内核启动命令行中强制iommu为off(intel_iommu=off或iommu=off)。
关闭功耗管理:
processor.max_cstates=1 idle=poll pcie_aspm=off
- 将队列的个数设置为核心数(当前NUMA节点)
ethtool -L ethX combined 12
- 将中断绑定到当前NUMA节点
set_irq_affinity -x local ethX
- 按需修改Tx和Rx的ring size,值越大,越消耗资源但可以提供更好的转发频率:
ethtool -G ethX rx 4096 tx 4096
- 在路由时关闭GRO特性
由于已知的内核问题,在路由/转发时必须关闭GRO特性。
ethtool -K ethX gro off
- 关闭自适应中断调控并且设置一个静态值
ethtool -C ethX adaptive-rx off adaptive-tx off
ethtool -C ethX rx-usecs 64 tx-usecs 64
- 关闭防火墙
sudo systemctl disable firewalld
sudo systemctl stop firewalld
- 开启IP转发
sysctl -w net.ipv4.ip_forward=1
7.2 低时延
- 关闭超线程(逻辑核)
- 确保网络设备绑定在NUMA节点0
- 使用taskset -c 0将benchmark绑定到0号核
- 关闭irqbalance服务
systemctl stop irqbalance
systemctl disable irqbalance
- 执行设置亲和性脚本将负载均衡到所有核上 - 尝试local或all
- 关闭自适应中断调控
ethtool -C ethX rx-usecs 0 tx-usecs 0 adaptive-rx off adaptive-tx off rx-usecs-high 0
- 使用标准的benchmark,比如netperf -t TCP_RR或netperf -t UDP_RR或netpipe。