跳到主要内容
博客

低延迟服务器与BIOS调优:isolcpus、NUMA绑核、C-State与中断亲和的完整清单

时间: 2026-10-27

同一套交易程序,在这台服务器上延迟 3 微秒,换一台就跑到 8 微秒——代码一行没改,差距全是机器给的。

这是低延迟团队都踩过的坑。服务器出厂时,BIOS 和操作系统按“通用负载”配置:省电优先、公平调度优先、综合吞吐优先。这些默认值对普通业务是好设定,对低延迟业务却每一项都是负债。低延迟调优的第一课,就是把机器从“为所有人设计”改回“为这一条热路径设计”。

调优清单不短,但逻辑主线只有一条:消灭一切可能打断热路径的东西。这篇文章按 BIOS、内核、NUMA、中断、验证五层,把完整清单过一遍。

BIOS 层:先把硬件的“自作主张”关掉

操作系统之前,BIOS 先决定硬件的行为模式。这一层有几项必查。

C-State 全部关闭。 C-State 是 CPU 的省电休眠档位,档位越深省电越多,但从深睡眠唤醒需要数十微秒——对微秒级延迟的系统,这是最昂贵的“省电”。BIOS 里把 C-State 设为 Disabled 或仅保留 C1,让核心永远在线。

P-State 与频率策略锁定。 CPU 动态调频意味着频率随负载浮动,同一段代码在低频核上就是跑得慢。电源策略设为 Performance,锁定全核最高频率。Turbo Boost 是否开启有讲究:全核高负载时 Turbo 引入频率波动,部分团队倾向关掉换确定性;单线程轻负载场景则可保留,取其瞬时高频。结论要靠实测,不能凭感觉。

超线程(Hyper-Threading)关掉。 超线程让两个逻辑核共享一套物理执行单元,对吞吐型负载是福利,对延迟型负载是互相干扰的室友——同物理核上的另一个线程随时可能挤占流水线。低延迟机器上,一个物理核只干一件事。

其他顺手项。 关闭节能型内存模式、关闭不需要的外设控制器、确认 PCIe 链路跑在标称速率和宽度上。

内核层:isolcpus 三件套

进入 Linux,第一件大事是把热路径要用的 CPU 核心从操作系统的视野里“圈出去”。内核启动参数里经典的三件套:

isolcpus 把指定核心从调度器里摘除——普通进程永远不会被调度到这些核上,它们留给绑核后的关键线程独享。

nohz_full 关闭这些核心上的定时器滴答。默认内核每核每秒有数百次时钟中断,每次中断都是热路径上的一次打断;nohz_full 让跑满用户态任务的核心不再周期性被打扰。

rcu_nocbs 把 RCU 回调从这些核心挪走,消除另一类内核级的周期性干扰。

三件套配套的还有:透明大页按场景取舍(低延迟分配路径上的 THP 合并会带来抖动,常用 madvise 模式精细控制)、vm.swappiness 压低避免交换、日志和审计子系统的开销裁剪。内核参数不是抄来的,每一台机器的角色不同,清单要跟着角色走。

NUMA 与绑核:让数据和计算待在同一个节点

多路服务器里,CPU 插槽和内存控制器是分组绑定的——这就是 NUMA。核心访问自己节点的内存是本地访问,跨节点访问要过互联总线,延迟可以高出近一倍。一次跨节点的内存访问,可能就是几十纳秒的隐形税。

绑核(CPU affinity)解决的是另一个问题:线程被调度器在核心间迁移,每次迁移都意味着缓存全废、TLB 重建。用 taskset 或 sched_setaffinity 把关键线程钉死在固定核心上,缓存热度才能积累起来。

两件事要合在一起做:线程绑在哪个核,它用的内存就得在哪个 NUMA 节点。numactl 的 --cpunodebind 和 --membind 要成对出现。还有一个经常被漏掉的环节:网卡。网卡插在哪个 PCIe 插槽上、归属哪个 NUMA 节点,收包线程就该绑在哪个节点——行情数据从网卡进内存再走互联总线绕一圈,这种冤枉路在配置层面就该堵死。

中断亲和:别让网卡中断满屋子乱跑

网卡收到数据包,靠中断通知 CPU。默认情况下中断由 irqbalance 动态分发到任意核心——包括你精心隔离出来的热路径核心。一次网卡中断落到策略线程的核上,就是一次数千纳秒的现场。

处置分三步:

关掉 irqbalance,中断分发收归人工管理。

设置中断亲和性(IRQ affinity),通过 smp_affinity 把每个中断源指定到固定核心。原则是把中断引到隔离核之外的“杂务核”上,热路径核心一个中断都不接。

网卡多队列逐个绑。 现代网卡有多个收发队列,每个队列一个中断号。把队列中断均匀钉到指定杂务核上,或者用 XPS/RPS 机制精细控制收发路径的核间分布。有些团队更进一步:干脆用轮询模式(busy polling)取代中断——付出一个核 100% 空转的代价,换中断延迟归零。值不值,看延迟预算有多紧。

验证:调优不是一次性工程

清单执行完,工作只完成一半。调优的效果要用数据验证,而不是用“感觉流畅了”结案。

建基线。 cyclictest 测量调度延迟,应用层埋点测端到端延迟,分别记录平均值、P99、P99.9 和最大值。调优前后各测一遍,每一项改动单独归因——一次改十项再测,出了问题不知道是哪项引起的。

跑满时间维度。 只测十分钟的基线是自欺。深夜批任务、备份窗口、日志切割,都可能在你没测的时段制造抖动。基线至少覆盖完整的业务周期。

纳入变更管理。 BIOS 升级、内核补丁、固件更新,任何一项都可能悄悄改回默认行为。调优配置要写成可重复执行的脚本和文档,每次变更后回归基线。低延迟的敌人不是慢,是不知不觉的退化。

写在最后

这份清单没有高深理论,全是体力活和细节账:C-State 关掉、核心隔离、绑核、中断归位、基线回归。真正的门槛不在知道,而在每一项都做到位、且长期保持到位。

这也是为什么越来越多机构选择把这一层交给专业的硬件方案。盛立科技的解决方案里有面向低延迟场景的定制化超频机,硬件选型、BIOS 参数、系统调优在出厂前完成一体验证,机构拿到的是一台“调优已完成”的机器,而不是一份需要自己啃的清单。盛立科技在极速交易领域深耕近二十年,早年与华为的合作项目曾入围科技部重点研发专项,2026 年又先后与智臾科技(DolphinDB)达成战略合作、获香港交易所年度大奖。纳秒级的竞争,最后拼的都是这些看不见的地面功夫。

常见问题

Q1:低延迟服务器为什么要关闭 C-State?

C-State 是 CPU 的省电休眠机制,深度睡眠档位唤醒需数十微秒,对微秒级延迟系统不可接受。BIOS 中关闭或仅保留 C1,可让核心始终在线,消除唤醒延迟造成的尾部抖动。

Q2:isolcpus、nohz_full、rcu_nocbs 分别起什么作用?

三者是内核启动参数“三件套”:isolcpus 将指定核心从调度器摘除供关键线程独享;nohz_full 关闭这些核心的定时器滴答中断;rcu_nocbs 移走 RCU 回调。共同为热路径打造无打扰的专属核心。

Q3:NUMA 绑核要注意什么?

两个原则:线程与其使用的内存必须在同一 NUMA 节点(跨节点访问延迟高近一倍);收包线程要与网卡所在的 PCIe 节点绑定。numactl 的 cpunodebind 与 membind 需成对使用。

Q4:中断亲和性(IRQ affinity)怎么配置?

先关闭 irqbalance 自动分发,再通过 smp_affinity 把每个中断源固定到指定核心。原则是将网卡队列中断全部引向杂务核,热路径核心不承接任何中断;极端场景可用 busy polling 轮询模式彻底取代中断。

Q5:超线程对低延迟系统有什么影响?

超线程让两个逻辑核共享一套物理执行单元,同核线程会互相挤占流水线资源,引入不可预测的延迟波动。低延迟服务器通常关闭超线程,保证一个物理核只执行一个关键线程。