2. 延迟的来源分析:网络延迟、操作系统延迟、应用层延迟、硬件延迟

做市引擎的核心就是跟时间赛跑。你想想看,别人比你快1微秒,你的订单可能就吃不到那笔利润。所以,搞清楚延迟到底从哪来的,是优化的第一步。

我个人习惯把延迟分成四个层面:网络、操作系统、应用层、硬件。每个层面都有它的“坑”。咱们一个一个来拆。

2.1 网络延迟:你躲不开的物理定律

网络延迟,说白了就是数据在网线上跑的时间。光速是固定的,但实际传输中,影响因素可不少。

  • 传输延迟:光纤长度决定。上海到深圳,光速往返大概10毫秒。这个你改不了,只能靠机房选址。
  • 处理延迟:交换机、路由器处理数据包的时间。我见过有些团队用廉价交换机,结果延迟比专业级的高出好几倍。
  • 排队延迟:数据包在交换机缓冲区里排队。流量一拥塞,延迟就飙升。

核心观点:网络延迟是“硬”延迟,物理定律摆在那。我们能做的,就是减少中间跳数、用更好的硬件。

我在项目中遇到过一件事:某次做跨交易所套利,发现延迟总是不稳定。排查了半天,最后发现是机房到交易所的链路里多了一台老旧的交换机。换掉之后,延迟直接降了30%。

2.2 操作系统延迟:你以为是软件,其实是“调度”

操作系统延迟,很多人容易忽略。你写个C++程序,觉得代码跑得飞快,但操作系统在背后搞了很多“小动作”。

  • 上下文切换:线程切换时,CPU要保存状态、加载新状态。一次切换几十微秒,高频交易里这就是灾难。
  • 中断处理:网卡收到数据包,CPU要暂停当前工作去处理中断。中断一多,延迟就乱跳。
  • 调度延迟:你的线程不一定能立刻拿到CPU。操作系统可能先让别的线程跑。

避坑指南:我曾经在一个项目里,发现延迟偶尔会飙到几百微秒。查了很久,原来是系统里有个定时任务在整点触发,抢了CPU。后来我把做市引擎绑到独立CPU核心上,问题就解决了。

嗯,这里要注意:操作系统不是实时系统。你写的代码再快,调度一乱,全白搭。所以,很多低延迟系统会做“CPU隔离”和“中断绑定”。

2.3 应用层延迟:你的代码才是“罪魁祸首”

应用层延迟,说白了就是你自己写的代码有多烂。我见过不少团队,硬件和网络都优化到极致了,结果代码里一堆坑。

  • 内存分配:new/delete 或者 malloc/free,一次分配可能几十微秒。高频交易里,这不能忍。
  • 锁竞争:多线程抢锁,抢不到就阻塞。阻塞一次,几百微秒就没了。
  • 系统调用:每次 read/write 都要陷入内核。陷入一次,几微秒到几十微秒。
  • 日志打印:很多人喜欢在关键路径上打日志。日志一多,延迟就上去了。
// 错误示例:每次交易都打印日志
void on_trade(const Trade& t) {
    log("Trade executed: price=%f, qty=%d", t.price, t.qty);  // 系统调用!
    process_trade(t);
}

// 优化后:异步日志,或者干脆不打印
void on_trade(const Trade& t) {
    process_trade(t);
    // 日志由另一个线程异步处理
}

警告:别小看日志。我曾经见过一个系统,因为日志打印太频繁,导致延迟从10微秒飙到500微秒。去掉日志后,一切恢复正常。

你想想看,一个交易流程里,可能涉及几十次内存分配、几次锁竞争、几次系统调用。每个环节多花几微秒,加起来就是几百微秒。在纳秒级竞争的做市领域,这基本等于“出局”。

2.4 硬件延迟:从CPU到网卡,每个环节都有“坑”

硬件延迟,很多人觉得“买贵的就行”。其实没那么简单。硬件延迟包括CPU、内存、缓存、网卡、PCIe总线等。

  • CPU延迟:指令执行、分支预测失败、缓存未命中。一次缓存未命中,几十纳秒到几百纳秒。
  • 内存延迟:从内存读数据,大概几十纳秒。但如果是NUMA架构,跨节点访问可能翻倍。
  • 网卡延迟:从网卡收到数据包,到数据到达应用程序,中间有DMA、中断、驱动处理。
  • PCIe延迟:数据在PCIe总线上传输,一次传输几百纳秒。
硬件环节 典型延迟 优化方向
L1缓存命中 ~1 ns 数据局部性优化
L2缓存命中 ~5 ns 减少数据大小
主内存访问 ~50 ns NUMA亲和性
PCIe传输 ~500 ns 使用更快的PCIe版本
网卡DMA ~1 μs 使用用户态驱动

核心观点:硬件延迟是“物理”的,但你可以通过软件来“绕过”它。比如,用用户态驱动绕过内核,用大页减少TLB miss。

我记得有一次,我们团队换了一款支持“零拷贝”的网卡,延迟直接从5微秒降到了1微秒。效果立竿见影。

2.5 延迟来源全景图

下面这张图,是我自己总结的延迟来源全景。你可以看到,每个层面都有它的“贡献”。优化的时候,要全局考虑,不能只盯着一个点。

做市引擎延迟来源全景图 网络延迟 传输延迟 | 处理延迟 | 排队延迟 典型范围:1μs - 10ms 操作系统延迟 上下文切换 | 中断处理 | 调度延迟 典型范围:1μs - 100μs 应用层延迟 内存分配 | 锁竞争 | 系统调用 | 日志 典型范围:100ns - 1ms 硬件延迟 CPU缓存 | 内存访问 | PCIe | 网卡DMA 典型范围:1ns - 1μs 延迟从下往上逐层累积,优化需从最底层开始

这张图想表达的是:延迟是层层叠加的。硬件延迟是基础,操作系统在上面加了一层,应用层再加一层,网络再一层。你优化了应用层,但硬件和操作系统没动,效果有限。反过来,你把硬件和操作系统优化好了,应用层稍微差一点,整体延迟也能接受。

我的建议:做延迟优化,先从最底层开始。先搞定硬件和操作系统,再优化应用层。别一上来就改代码,结果发现瓶颈在网卡上。

好了,这一章我们拆解了延迟的四个来源。每个来源都有它的“脾气”。下一章,我们会聊聊怎么测量这些延迟。毕竟,你连延迟在哪都不知道,怎么优化?


公众号:蓝海资料掘金营,微信deep3321