Andrew Hunter:低延迟系统的性能工程

原标题Andrew Hunter on Performance Engineering for Low-Latency Systems

超大规模环境中的微小优化为何值得投入?交易延迟为何更难衡量?性能分析、追踪、语言设计和硬件又如何相互配合?

AHAndrew Hunter嘉宾 · Jane Street
频道
Jane Street
发布
2023年11月29日
视频
55:34
阅读
12 分钟
原文
英语
在 YouTube 打开
往下滚动阅读时,视频会缩到右下角继续播放。字幕跟随阅读语言。
阅读语言共 2 种语言可读
由 AI 从英语原文翻译。打开“对照原文”可以逐段核对。
摘要

30 秒看懂

Jane Street 工程师 Andrew Hunter 与 Ron Minsky 对比了 Google 规模的基础设施性能工作和对延迟敏感的交易系统。他们探讨采样分析器、Magic Trace 与可视化,以及 OCaml 数据布局、硬件卸载和快速反馈的价值。

  1. 1优化目标丰富在超大规模环境中,共享基础设施运行得足够频繁,即使微小收益也值得投入大量工程工作。
  2. 2衡量关键时刻延迟分析关注特定决策期间的执行路径,而非整体平均 CPU 使用情况。
  3. 3隐藏的 200 微秒延迟低优先级队列延迟了订单,尽管决策和发送各自的计算开销都很小。
  4. 4看清汇聚的成本图形视图能揭示多条路径共同调用的高成本函数,即使这些路径在火焰图中单独看来都很小。
  5. 5布局很重要装箱值和指针可能带来成本;一种应对方法是在紧凑布局之上生成接口。
  6. 6缩短反馈循环贴近真实情况的测试环境可以把等待数天生产结果的过程缩短为十分钟的迭代。

要点建议

  1. 在超大规模环境中,对共享基础设施的小幅改进也能为整个机器集群创造可观价值。
  2. 优化延迟需要衡量关键事件发生时的情况,而不仅是平均 CPU 使用率。
  3. 采样和追踪回答不同的问题,也有不同的开销。
  4. 数据布局和系统架构可能比单纯选择编程语言更重要。
  5. 加快反馈循环既能改善人的工作流程,也能加快性能工程。
全文

按章节阅读整理后的全文

只看原始文稿
01

对细节的着迷

Hunter 讲述了他如何从操作系统实现、研究生研究和生产软件中学习。

Ron Minsky 介绍了 Andrew Hunter:他是 Jane Street 市场数据团队的工程师,拥有性能工程背景。Hunter 说,尽管他能给工作找出很多实际理由,但他最着迷的是理解系统并让它运行得更快。

Minsky 认为,专业能力需要对 CPU、互连和编译器的细节抱有浓厚兴趣。Hunter 回忆,他学习操作系统时会阅读 Linux 对各个主题的实现,包括虚拟内存,并继续追问由此产生的问题,而不会因为它们超出课程范围就停下来。

研究生期间,Hunter 参与了一个图遍历系统项目,用软件重现专用硬件。真正有趣的挑战不仅是算法,还包括理解内存控制器、并发访问、停顿,以及系统能同时保持多少操作进行中。

在 Google 的暑期实习让 Hunter 看到,大规模系统研究可以部署到生产环境并得到使用。他强调,提交大学项目与维护接触真实数据的软件不同:用户会带着意外行为回来,而这些反馈会推动下一轮改进。

02

超大规模与数据中心税

共享基础设施让小优化在庞大的机器集群中产生更大作用。Jane Street 的成本与延迟特征则有所不同。

Hunter 把超大规模企业的优化称为“简单模式”,因为规模创造了大量有价值的目标,而不是因为修复本身容易。当足够多的机器运行共享基础设施时,即便内存分配、序列化或编译器生成代码的成本只下降一点,也足以回报大量工程投入。

他提到“数据中心税”:各种应用共享基础设施,而这一层消耗了相当比例的计算周期。改进公共层可以同时惠及许多服务,尽管单个应用自身的业务逻辑也可能提供最大的优化机会。

Minsky 将这一点与成本结构联系起来:硬件、电力和查询量让整个机器集群的小幅改进变得有价值。Hunter 说,优化人人共用的组件时,他不必知道应用提供的是搜索服务还是猫咪视频。

Jane Street 没有同样的规模,因此节省平均 CPU 周期未必足以支持一个项目。低延迟交易系统常常在紧密循环中轮询网络数据包,大部分时间有意保持空闲;传统性能分析器可能主要报告这些空转。

Minsky 补充说,Jane Street 有许多种软件,上述描述尤其适用于交易系统。它们的设计目标是快速响应、处理突发流量,而非在平静时段最大限度提高利用率。相比之下,历史模拟属于吞吐量工作负载,处理越快,研究人员就越早得到结果。

小幅改进仍然可以累积。Minsky 说,编译器性能提高 1% 与其他收益结合起来就有意义;Hunter 则形容这是逐步消除系统中的余量。单项改变可能低于噪声水平,因此工程师有时需要单独测试,或依靠对机制的理解。

03

机械共情与延迟

经验丰富的工程师学会将抽象与硬件联系起来。延迟分析关注关键时刻发生的事情。

Hunter 对“每一项性能改动都必须先由性能分析证明有价值”的规则提出质疑。在性能敏感的代码中,只要不带来过多复杂度或风险,默认选择高效方案是合理的。经验和“机械共情”能帮助工程师判断机器实际会做什么。

Hunter 解释,机械共情是后天形成的直觉,用来理解高级代码与物理执行之间的关系。不同语言提供不同的抽象,但内存布局、加载、算术运算和编译后的分支都有实际成本。专家会逐渐形成对这些后果的直觉,而不是每次都从头重建整个模型。

困难模式的优化往往关注某个关键时刻的延迟,而非平均资源使用情况。性能分析器可以告诉你程序把 20% 的时间花在哪里,但交易工程师想知道的是分析某个市场事件或发送订单时发生了什么。

Minsky 指出,这让调查与业务逻辑紧密相连:需要关注的是做出决策的执行路径。Hunter 同意,基础设施有时也会影响关键时刻,但重要代码通常是交易系统自身的决策路径。

04

采样与追踪

Perf 和内存分配分析揭示总体成本,但一个延迟的订单说明时间线也不可或缺。

采样性能分析器定期中断程序,记录当前指令位置,通常也记录调用栈,然后让程序继续运行。Hunter 喜欢 Linux perf:它利用硬件设施高效收集样本;性能分析结果本质上是一组调用栈,可以聚合后展示热点。

采样不必仅由经过的 CPU 周期触发。缓存未命中或分支预测失败等硬件事件,也能让分析集中在这些高成本事件发生的位置。内存分配分析同样能揭示分配发生在哪里,虽然它衡量的不是时间。

Minsky 说,高性能 OCaml 代码通常会尽量让热点路径上的堆分配接近零。Hunter 指出,在经过优化的 C++ 系统中,内存分配也可能占据相当成本:即使某些分配不可避免,性能分析仍可能发现程序分配得比实际需要更多。

采样以牺牲细节换取较低开销,但如果问题是某个关键瞬间发生了什么,这种取舍就会带来困难。Hunter 回忆一个系统:决定发送订单和实际发送订单各自都很快,但订单仍在做出决定约 200 微秒后才发出。

原因是一个低优先级工作队列和一个较旧的 API:后者假设外发流量可以等到系统空闲时处理。改用立即执行的 API 后,延迟得到解决。CPU 成本分析无法揭示这个关键问题,因为它出在两个各自开销很小的操作之间。

Jane Street 开发的 Magic Trace 能回顾一小段执行过程。它展示函数调用随时间发生的顺序,而非聚合样本。它的开销更高,但时间线能直接显示普通性能分析可能遗漏的关系。

两位讲者提醒,性能分析和追踪的术语并不统一。RPC 追踪可能捕获一次请求的完整消息链;Memtrace 对内存分配进行采样,但会追踪每个选中分配的整个生命周期。对部分对象或请求捕获完整生命周期,能回答的问题与采样孤立时刻不同。

05

Magic Trace 与可视化

Processor Trace 通过硬件记录执行历史。追踪视图、火焰图和 pprof 展现不同的模式。

Magic Trace 使用 Intel Processor Trace,这是一项硬件设施,可以将压缩后的执行信息记录在环形缓冲区中。缓冲区保存一小段历史,通常是几毫秒;感兴趣的事件发生时就可以捕获它。这种方法依靠芯片支持以及 perf 与该功能的集成。

Minsky 希望这种硬件能力能配备更易使用的工具。Hunter 同意,性能分析常常要求人们掌握大量冷僻的参数和处理器行为知识。更好的默认设置与界面可以让人们不必先成为每种工具的专家,也能得到有用的答案。

Minsky 还见过人们用 Magic Trace 解决普通吞吐量问题:即使在任意时刻抓取的追踪,也可能让执行过程更容易理解。Hunter 举例说,一个热点可能代表一次缓慢调用,也可能代表一千次意外重复的低成本调用;时间线可以让循环一目了然。

可视化是 Hunter 工作的重要部分。火焰图通过宽度显示采样调用栈所占比例,改进了以往的视图;但它可能掩盖一个经多条不同调用路径到达的函数:即使总成本很大,每处单独看来仍可能很小。

Hunter 介绍了 pprof 的图形视图:函数是节点,带权重的箭头连接调用方与被调用方。多条小路径可以明显地汇聚到一个函数。内存分配是常见例子:许多不同的业务逻辑都可能调用 malloc。

翻转火焰图在某些情况下有帮助,但如果分析人员尚不知道该关注哪个函数,调用栈中间的汇聚点仍然难以处理。Minsky 认为图形视图不那么直观,Hunter 也同意可视化还有改进空间。

06

尾延迟与采样的取舍

流量突发时,普通工作排队也可能导致长尾。采样仍适合分析吞吐量,而且开销较低。

如果系统通常在 5 微秒内响应,偶尔却需要 1 毫秒,尾延迟就很重要;尤其是繁忙时刻可能恰恰是最需要速度的时候。追踪可以显示重大垃圾回收等异常事件,但长尾并不总由特殊情况造成。

流量突发可能只是让普通工作排起队。如果处理每个数据包需要 1 微秒,而到达速率实际上只给系统留下每包 800 纳秒,系统就会逐渐落后。批处理有时可以解决问题;否则可能需要加快反复执行的操作本身。

Hunter 希望能在追踪中选取一个范围,并把其中的调用显示为聚合性能分析视图。Minsky 区分了对这种可视化的需求与另一个独立问题:采样是否比完整追踪更合适。

采样适合历史研究和机器学习训练等吞吐量问题,硬件计数器也可以针对特定事件。采样的成本更低:Hunter 估计 Intel Processor Trace 可能带来约 5% 到 15% 的开销,因此 Jane Street 只在需要时选择性开启,而不是始终在所有地方运行。

Hunter 仍希望能获得交易系统的广泛采样视图,并排除空闲轮询,以便比较整个系统中发送订单、解析市场数据等方面的优化机会。

07

OCaml、C++ 与布局

无论使用什么语言,架构和避免不必要的工作都很重要。Hunter 介绍了 OCaml 数据表示的成本及实际应对方法。

谈到从 C++ 转向 OCaml,两位讲者都不认同使用 C++ 就能自动让软件变快的假设。架构、进程边界、数据结构以及系统选择执行哪些工作,都可能比语言选择更重要。

Hunter 说,首要任务往往是避免不必要的工作:如果可以重新设计系统,就不要调用那个函数、读取那个数据源或执行那个操作。两行代码的改动可能带来很大收益,但前提是经过数周调查,弄清楚它为何有效。

他将 OCaml 的性能挑战分为三类。代码生成不够成熟,可能产生多余的分支或寄存器溢出,这很烦人,但通常不是主要瓶颈。垃圾回收也对内存初始化和引用提出要求,在某些情况下会带来成本。

Hunter 认为最重要的挑战是数据表示。OCaml 数据结构常使用装箱值和指针,而 C++ 的表示方式可能直接把数据内联存放。这些选择有利于编写整洁、安全的代码,但可能增加内存占用,让物理布局更难控制。

Jane Street 使用领域特定语言描述数据包布局,并在紧凑的底层内存表示之上生成可用、类型安全的接口。同样的方法可以将内存中的市场订单簿表示为扁平、紧凑的形式;不过,这种形式不如普通 OCaml 易用,因此只用于确有必要的地方。

团队还使用一种零分配的 OCaml 方言,以及能更好控制布局和垃圾回收交互的语言特性。C 桩函数提供另一条出路:Hunter 说,跨越这个边界的调用开销可能很低,同时他也粗略地与 Java 的 JNI 做了比较。

编译器工作旨在让普通 OCaml 类型拥有更灵活的布局控制。在此之前,团队可以通过架构、预处理和跨进程分配工作来补偿。Minsky 指出实际代价:当一种优化更难表达,人们就不一定会去做。

Hunter 说,自律也包括在慢代码无关紧要时不去修改它。性能专家可能会对一次不必要的分配感到难以忍受,但还有更重要的问题需要他们投入时间。

08

硬件与反馈循环

FPGA 可以加速简单任务,不同系统也需要不同的延迟目标。快速反馈有助于研究和工程工作。

Minsky 提问:如果延迟至关重要,系统为什么还要使用 CPU?他估计,在普通数据包处理路径中,数据每次经过 PCI Express 的单程耗时约 400 纳秒;而连接网卡的 FPGA 可以在不到 100 纳秒内处理并返回数据包。

Hunter 说,硬件会改变架构选择,但硬件开发很困难,复杂交易逻辑可能不适合在硬件中实现。系统可以把简单、规模小且对速度要求极高的任务交给硬件,再用更灵活的软件系统向它提供数据。

合适的延迟目标取决于任务。Hunter 描述的工作既包括不到 100 纳秒的交易,也包括通过邮件沟通、第二天才收到回复的交易。一个系统的目标是将尾延迟从 50 毫秒降到 1 毫秒;更简单、更看重速度的系统可能以 20、10 或 5 微秒为目标。

面向人的延迟同样重要。编辑器卡住或价格显示缓慢会干扰工作;如果研究系统能在一分钟内反馈交易想法的结果,实验节奏就会与耗时一天的系统截然不同。

Minsky 观察到,更快的反馈让创造性迭代成为可能。Hunter 提到 John Boyd 的 OODA 循环——观察、判断态势、决策、行动——并将其与加速烈酒陈酿相比较:即使这一过程有争议,更短的反馈周期也让人们能在相同时间内进行更多实验。

同样的原则适用于工程实验。贴近真实情况的测试环境如果能在十分钟内回答一项改动是否有效,工程师尝试和修正想法的速度就远快于等待数天生产数据。Minsky 说,重视细节的习惯可以跨环境迁移,包括浏览器性能工作。

Hunter 开玩笑说,性能工作要求人们觉得那些据说枯燥的细节很有意思。Minsky 也认为,很难向业内以外的人解释这种吸引力。对话最后,Hunter 讲述了父亲曾担心计算机科学能否提供可靠职业的故事。

同频道的其他文章

6 张幻灯片15:33EN → 简体中文
JSJane Street· 2026年10月26日Figgie 策略:解读手牌、争夺多数与定价Bradley, Mike · Jane StreetJane Street 交易员 Bradley 和 Mike 分析三局游戏,展示私人信息、市场竞争和时机如何影响牌价。Decision MakingMathematicsFintech
1:48:29EN → 简体中文
JSJane Street· 2026年10月16日AI 如何改变编程:John Krazit 与 Ron Minsky 的对话Ron Minsky, John Krazit · Jane StreetJane Street 的 AI 工具负责人和 Signals and Threads 主持人探讨智能体基础设施、安全、代码审查,以及软件开发体验的变化。编程智能体Developer productivity评估+2
1:36:37EN → 简体中文
JSJane Street· 2026年9月23日Aaron Bauer:在 AI 时代教授软件工程Ron Minsky, Aaron Bauer · Jane Street当模型能够生成代码时,学习目标、主动练习和编辑器设计如何影响工程教育。AI in EducationSoftware engineeringEducation+2
9 张幻灯片1:05:45EN → 简体中文
JSJane Street· 2026年9月11日Cyrus Omar:实时编程与人与 AI 共享的计算公共空间Cyrus Omar通过 Hazel 演示,探讨即时反馈、结构化协作和精细权限如何帮助人类与 AI 智能体共同工作。Programming LanguagesHuman-AI Collaboration开发流程与测试+2
1:25:00EN → 简体中文
JSJane Street· 2026年9月2日Eric Mannes:如何将杂乱的外部数据用于交易研究Ron, Eric Mannes · Jane Street从商品期货和 Excel 风险系统,到时点数据集和 AI,Eric Mannes 解释 Jane Street 数据工程背后的领域知识。Data quality & curation开发流程与测试Investing+2
7 张幻灯片1:16:29EN → 简体中文
JSJane Street· 2026年8月26日Grant Sanderson 与 Alok Puranik:从群论看位置编码Grant Sanderson, Alok Puranik · 3Blue1Brown从注意力机制的假设出发,他们推导矩阵指数,并将旋转、衰减和 Jordan 块与 RoPE、ALiBi 联系起来。Transformers & attentionMathematics机器学习基础+1