3、操作系统调优:Linux内核参数优化

做高频交易的人都知道,操作系统不是拿来就用的。默认的Linux内核,说白了是为通用场景设计的——它要照顾数据库、Web服务器、桌面用户。但咱们做高频策略,要的是极致的低延迟和确定性。

我个人习惯,每拿到一台新机器,第一件事就是做内核参数调优。这不是锦上添花,而是生死攸关。你想想看,一次上下文切换多花几十微秒,在纳秒级竞争的市场里,这差距足以让订单排到队尾。

CPU隔离与中断亲和性

CPU隔离,就是把某些CPU核心从系统的进程调度中剥离出来。这些核心只跑你的交易策略,别的进程别来打扰。

具体怎么做?我一般在grub启动参数里加isolcpus。比如:

isolcpus=2,3,4,5 nohz_full=2,3,4,5 rcu_nocbs=2,3,4,5

这里把CPU 2-5隔离出来。同时开启nohz_full,减少时钟中断的打扰。rcu_nocbs是把RCU回调也挪走。

注意: 隔离CPU后,系统默认不会把进程调度到这些核心上。你得手动绑定你的策略进程。用taskset或者cset都行。

中断亲和性,这是个容易被忽略的点。网卡中断来了,如果落在你策略所在的核心上,那延迟就炸了。我建议把中断绑定到非隔离核心上。

查看当前中断分布:

cat /proc/interrupts | grep eth0

修改亲和性:

echo 1 > /proc/irq/<中断号>/smp_affinity

这里的1是CPU掩码,表示绑定到CPU 0。如果你有4个核心,掩码分别是1、2、4、8。

我的经验: 我曾经在一个项目中,发现策略偶尔出现毫秒级的抖动。查了两天,最后发现是网卡中断落在了策略核心上。把中断挪走后,抖动直接消失了。嗯,这种坑踩过一次就记住了。

内存大页与透明大页

内存分页,默认是4KB一页。对于高频交易来说,这太小了。TLB(页表缓存)很容易被撑爆,导致内存访问变慢。

大页(HugePages)就是解决这个问题的。把页大小改成2MB甚至1GB,TLB的覆盖范围瞬间扩大几百倍。

配置大页:

echo 1024 > /proc/sys/vm/nr_hugepages

这分配了1024个2MB的大页,总共2GB。然后你的程序需要用mmap加上MAP_HUGETLB标志来使用这些大页。

但这里有个坑——透明大页(Transparent HugePages)。

透明大页是内核自动把普通内存页合并成大页。听起来很美,但实际在高频场景下是个灾难。为什么?因为它会在后台做内存规整(compaction),这个过程会触发大量页面迁移,导致不可预测的延迟。

强烈建议: 关闭透明大页。我见过不止一个团队,因为开着透明大页,策略时不时出现几十毫秒的卡顿。排查起来极其痛苦。

关闭方法:

echo never > /sys/kernel/mm/transparent_hugepage/enabled
echo never > /sys/kernel/mm/transparent_hugepage/defrag

我个人习惯,在/etc/rc.local里加上这两行,确保重启后也生效。

文件系统选择:XFS vs EXT4

高频交易对文件系统的要求很明确:低延迟、高并发、日志开销小。

EXT4是老牌选手,稳定可靠。但它的日志机制(journal)在高频写入场景下,会有一定的性能开销。尤其是当你有大量小文件操作时,EXT4的锁竞争会比较明显。

XFS是后起之秀,设计上更注重大文件和高并发。它的分配组(allocation group)机制,允许多个线程同时写入不同区域,锁冲突少很多。

特性 EXT4 XFS
最大文件大小 16TB 8EB
最大文件系统 1EB 8EB
日志开销 中等
高并发写入 一般 优秀
碎片整理 支持 支持

我的建议:如果只是存日志和配置文件,EXT4完全够用。但如果你的策略需要高频写入行情数据或订单记录,XFS会是更好的选择。

一个小技巧: 挂载XFS时,加上noatimenodiratime参数,可以避免每次访问都更新时间戳,减少不必要的磁盘写入。

网络协议栈调优

网络延迟是高频交易的核心瓶颈之一。Linux默认的网络协议栈,是为吞吐量优化的,不是为延迟优化的。

首先,调整网卡ring buffer。这个缓冲区如果太小,丢包;太大,延迟高。我一般设成2048或4096:

ethtool -G eth0 rx 4096 tx 4096

其次,开启RPS(Receive Packet Steering)和RFS(Receive Flow Steering)。这两个机制可以把网络中断分散到多个CPU核心上,避免单个核心成为瓶颈。

echo f > /sys/class/net/eth0/queues/rx-0/rps_cpus
echo 4096 > /sys/class/net/eth0/queues/rx-0/rps_flow_cnt

这里f表示使用CPU 0-3。

还有,调整TCP参数。高频交易通常用UDP,但如果你用TCP做行情或订单传输,这些参数就很重要:

net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1

这些参数说白了就是:加大缓冲区,减少TIME_WAIT状态的连接数,让TCP更快地回收资源。

注意: tcp_tw_reusetcp_tw_recycle容易混淆。我建议只用tcp_tw_reuse,别碰tcp_tw_recycle。后者在NAT环境下会导致严重问题,我踩过这个坑。

最后,如果你追求极致性能,可以考虑使用DPDK(Data Plane Development Kit)。它绕过内核协议栈,直接在用户态处理网络包。延迟可以从几十微秒降到几微秒。

但DPDK也有代价——你需要自己实现TCP/IP协议栈,或者用现成的库如libmoonf-stack。我个人只在最核心的行情接收链路上用DPDK,其他场景还是用内核协议栈,毕竟维护成本低很多。

总结一下: 操作系统调优不是一蹴而就的事。你需要根据你的策略特点、硬件环境、网络条件,反复测试和调整。我建议每次只改一个参数,然后做延迟测试,看看效果。别一次性改一堆,出了问题都不知道是哪个参数导致的。
Linux内核参数优化知识体系 CPU隔离 isolcpus参数 nohz_full减少时钟中断 rcu_nocbs挪走RCU回调 中断亲和性 绑定到非隔离核心 smp_affinity掩码 避免策略核心被中断 内存大页 HugePages 2MB/1GB 减少TLB miss mmap + MAP_HUGETLB 透明大页 ❌ 建议关闭 内存规整导致抖动 echo never 关闭 文件系统 XFS 高并发写入优秀 日志开销低 适合高频场景 EXT4 稳定可靠 锁竞争较明显 适合日志场景 网络协议栈调优 Ring Buffer调整(rx/tx 4096) RPS/RFS分散中断到多核心 TCP参数优化(缓冲区、TIME_WAIT) DPDK用户态网络(极致性能) 核心目标:降低延迟、减少抖动、提高确定性