第二章:性能指标与目标——延迟、吞吐量、抖动、可用性

做期权做市系统,说白了就是跟时间赛跑。你报单慢了一微秒,别人就抢在你前面成交了。我见过太多团队,一上来就堆硬件、上FPGA,结果连自己到底要优化什么都说不清楚。嗯,今天我们就来聊聊,做市系统的性能指标到底该怎么看,目标该怎么定。

2.1 延迟:最核心的指标

延迟,就是一条指令从发出到完成的时间。在期权做市里,我们通常关注这几个点:

  • 网络延迟:从你的服务器到交易所的物理时间。光速是极限,但实际走光纤、过交换机,都会增加。
  • 内核延迟:数据从网卡到用户态程序的时间。这里涉及中断处理、上下文切换。
  • 应用延迟:你的策略代码处理行情、计算定价、生成订单的时间。
  • 端到端延迟:从行情事件发生,到你的订单到达交易所的总时间。

我个人习惯,把端到端延迟拆成三段来测量:行情接收→策略计算→订单发送。每一段都要单独打时间戳,这样出了问题才能快速定位。

我曾经在一个项目中,发现端到端延迟突然从10微秒飙到50微秒。查了半天,原来是行情网关里一个日志打印函数没关,每次写日志都要等磁盘IO。你看,一个不起眼的print就能毁掉整个系统的延迟。

2.2 吞吐量:能扛多少并发

吞吐量,就是单位时间内能处理多少笔交易或行情。期权做市和股票不太一样,期权合约多,深度薄,波动大。你想想看,一个ETF期权可能有几十个行权价、多个到期月,加起来几百个合约。每个合约的行情都在变,你的系统得同时处理。

吞吐量的瓶颈通常在哪?

  • CPU核心数:单核处理能力有限,得靠多核并行。
  • 内存带宽:行情数据量大,频繁读写内存,带宽不够就卡住。
  • 锁竞争:多个线程抢同一个资源,吞吐量直接腰斩。
场景 典型吞吐量要求 常见瓶颈
单合约行情处理 10万笔/秒 CPU单核
全市场行情处理 100万笔/秒 内存带宽、锁
订单生成 5万笔/秒 策略计算复杂度

避坑指南:我曾经遇到一个团队,吞吐量测试时跑得很好,一上线就崩。为什么?因为测试时行情数据是均匀到达的,但真实市场有突发流量。比如某个期权突然大幅波动,一瞬间行情更新量暴增10倍。你的系统得扛得住这种尖峰。

2.3 抖动:比延迟更可怕

延迟高,你还能接受。但抖动大,你就没法预测了。抖动,就是延迟的波动幅度。比如平均延迟10微秒,但偶尔跳到100微秒。这种不确定性对做市策略是致命的。

为什么抖动这么讨厌?

  • 你的定价模型假设延迟是稳定的,结果突然变慢,报价就过时了。
  • 交易所的撮合逻辑是公平的,但你的订单总是晚到,就会被对手盘吃掉。
  • 抖动还会导致你的订单被拒绝,因为报价已经失效了。

抖动的来源有哪些?

  • 垃圾回收(GC):Java、C#等语言,GC一触发,所有线程都得停。
  • 系统中断:网卡中断、定时器中断,都会打断你的程序。
  • CPU频率切换:省电模式下,CPU会降频,性能就波动了。

注意:我个人习惯,在系统上线前会跑72小时的延迟分布测试。如果发现99.9百分位的延迟超过平均延迟的5倍,那这个系统就不能上线。抖动必须控制在微秒级。

2.4 可用性:不能断

做市系统是7x24小时运行的?不,交易时间就那么几个小时,但每一秒都不能断。可用性通常用几个9来衡量:

  • 99.9%:一年允许宕机8.76小时。对做市来说,这太长了。
  • 99.99%:一年允许宕机52.56分钟。勉强可以接受。
  • 99.999%:一年允许宕机5.26分钟。这才是做市系统的目标。

怎么保证可用性?

  • 主备切换:一台挂了,另一台立刻顶上。切换时间要控制在1秒以内。
  • 状态同步:主备之间的订单状态、持仓数据必须实时同步。
  • 熔断机制:如果系统检测到异常,比如延迟超过阈值,自动停止交易,防止造成更大损失。

我建议:可用性不是靠代码保证的,是靠流程保证的。每次发布前,必须做故障演练。我曾经在一次演练中,发现主备切换后,备机的行情数据落后了3秒。这3秒里,备机报出的价格全是错的。嗯,从那以后,我们加了一条规则:备机必须确认行情同步到1毫秒以内,才能接管交易。

2.5 如何设定合理的性能目标

很多团队一上来就说「我们要做到微秒级延迟」。但微秒级是什么概念?从上海到深圳的光纤来回就要10毫秒,你一个微秒的优化,在物理距离面前根本不值一提。所以,设定目标要务实。

我的做法是这样的:

  1. 先测量现状:用性能工具(比如perf、eBPF)跑一遍,看看当前系统的延迟、吞吐量、抖动是多少。
  2. 找瓶颈:是网络慢?还是CPU不够?还是锁竞争?用火焰图一看就清楚。
  3. 定目标:不要拍脑袋。比如当前端到端延迟是50微秒,你优化到30微秒是合理的,但你说要优化到1微秒,那可能得换硬件、换语言、甚至换交易所。
  4. 分阶段:先优化最明显的瓶颈,比如去掉日志、改用无锁队列。然后再优化次一级的,比如内存分配、CPU亲和性。
  5. 持续监控:目标不是定完就完了。上线后要持续监控,看看有没有退化。

避坑指南:我曾经见过一个团队,目标定的是「延迟低于10微秒」。结果他们把所有精力都花在优化网络层上,却忽略了策略计算本身就要5微秒。你想想看,策略计算都占了5微秒,网络层再怎么优化,也到不了10微秒。所以,目标要分解到每个环节,而不是只看最终结果。

2.6 知识体系图

下面这张图,把性能指标和优化目标的关系梳理清楚了。你可以把它当作一个检查清单,每次做性能调优时,对照着看一遍。

性能指标与目标 延迟 吞吐量 抖动 可用性 网络延迟 内核延迟 应用延迟 端到端延迟 CPU核心数 内存带宽 锁竞争 垃圾回收 系统中断 CPU频率切换 主备切换 状态同步 熔断机制 设定目标:测量现状 → 找瓶颈 → 定目标 → 分阶段 → 持续监控 目标要分解到每个环节,而不是只看最终结果

这张图把四个指标和它们的子项都列出来了。你每次做性能调优时,可以对照着看:我当前优化的是哪个指标?它的子项里,哪个是瓶颈?目标设定那一步,有没有分解到每个环节?