4. 端到端延迟定义:传输延迟、协议延迟、队列延迟、抖动等指标
做 CXL 延迟测量这些年,我经常被问到一个问题:你到底在测什么东西?大家嘴上都说“延迟”,但每个人脑子里想的数字其实不一样。有的人盯着链路传输时间,有的人关心协议握手成本,还有人被队列阻塞折磨得够呛。
我个人习惯先把端到端延迟拆成四个基本成分:传输延迟、协议延迟、队列延迟和抖动。这四个成分加在一起,才是你真实体验到的延迟。今天我们就挨个讲清楚。
4.1 传输延迟
这个最好理解。物理信号在走线、连接器、PCB 上传播需要时间。电信号在铜线里大约 5 ~ 6 ns/m,光信号在光纤里大约 4.9 ns/m。CXL 通常走的是高速串行差分对,线长从几厘米到几十厘米不等。
我记得有一次在调试一个 CXL 1.1 的原型板,链路训练总是超时。后来拿眼图扫了一遍,发现通道长度差了接近 20 cm。那 0.1 ns 的额外传播时间,直接让协议层误判了时序窗口。所以传输延迟虽然值小,但你不能忽略它。
4.2 协议延迟
协议延迟是 CXL.cache 请求从发起到完成,协议状态机消耗的时钟周期数。这包括:
- 请求打包:把 CPU 侧的读/写请求封装成 CXL 协议报文。
- Link 上传输:经过 FLIT(流量控制单元)格式化、CRC 计算、重传缓冲区。
- 目标端解包:把报文还原成内存/设备侧的内部请求。
- 响应打包/解包:同理。
说白了,协议延迟就是软件和硬件之间来回“翻译”的成本。你想想看,每多一层封装,就多几个额外周期。CXL.cache 的协议本身已经尽力压缩了,但 Retry 机制、Credit 交换、缓存一致性状态的切换都会增加额外开销。
我在项目中遇到过一种情况:设计团队为了省一个寄存器级,缩短了协议状态机的关键路径,结果导致 hold 违规,整个子系统的协议窗口垮掉。最后回头老老实实加了一拍 pipeline,协议延迟涨了 1 ns,但 timing 收敛了。所以这里不能一刀切追求最小延迟,要 tradeoff。
| 子阶段 | 典型延迟(@ PCIe 16 GT/s) | 说明 |
|---|---|---|
| 请求封装 | ~10 ns | 包含报头组装、CRC 插入 |
| FLIT 序列化 | ~4 ns | 按 66/64b 编码,加上符号位 |
| 响应解包 | ~8 ns | 解码、有效性检查 |
| Cache 状态更新 | ~5 ns | MESI 状态机跳转 |
4.3 队列延迟
这个最容易被人忘记,也最致命。队列延迟 = 请求在缓冲区里等待被处理的时间。CXL.cache 路径上有多个队列:
- 发送队列:主机端发出请求前的排队。
- 接收队列:设备端收到请求后的排序。
- 重排序缓冲区(Reorder Buffer):等待所有依赖请求完成。
- 回放队列:触发重传时的暂存。
队列延迟的主要来源是 背压(backpressure)。当下游处理速度跟不上上游发送速度时,队列开始堆积。而队列一旦变深,延迟就会迅速恶化。你想想看,一个请求本来只花 20 ns 处理,结果前面排了 100 个请求,那延迟直接变成 2 μs。
我在项目中遇到过最头疼的 case:一个 CXL Type-2 设备在做 burst 写入时,因为内部 SRAM 的 bank 冲突,导致读回放队列在短时间内增长了 30 倍。事后分析发现,根本不是链路问题,是队列调度策略太 naive。
想降低队列延迟,要么减少深度,要么缩短服务时间。但深度太小又会引起丢包重传,这是个平衡。
4.4 抖动
抖动不是平均延迟,而是延迟的变化量。为什么需要单独列一个指标?因为对于实时性要求高的场景(比如 CXL 用于加速器缓存一致性),平均延迟达标了,但抖动太大,依然会导致超时或者乱序。
抖动的来源:
- 链路层纠错重传:CRC 错误后重发一个 FLIT,增加随机耗时。
- Credit 回传不对称:流控 Credit 返回延迟不稳定。
- 仲裁冲突:多个虚拟通道(VC)争用物理链路。
- 电源噪声 / 时钟抖动:物理层面引入的随机抖动。
我个人测量抖动喜欢用直方图 + 分位数。只看平均值会骗人,99.9% 分位延迟才是真实体验。
4.5 延迟构成图:一眼看懂端到端的全局
我们把上面四个成分放在一张图里。你从发起到完成,每一笔 CXL.cache 请求都经过这些阶段。注意,抖动不是单独一个模块,它是对整条路径延迟的不确定性度量,所以我用虚线包围表示。
4.6 四个指标如何协同评估
最后给你一个我常用的测量清单。每次拿到新平台,我都按这个顺序走一遍:
- 测传输延迟:用回环模式发一个最小包,去掉协议开销,只看物理往返。如果超过理论最小值太多,查 PCB 走线。
- 测协议延迟:发一个无数据竞争的简单请求(比如读一个干净缓存行)。把传输延迟减掉,剩下的就是协议状态机耗时。
- 测队列延迟:逐步加大请求并发度,观察平均延迟曲线。当延迟开始非线性上升时,就是队列开始生效了。记录那个拐点。
- 测抖动:固定并发度(比如 8 个请求),采集 100 万笔延迟样本,看 99.9% 分位与 50% 分位的差值。
嗯,这四个指标搞清楚了,后面我们聊优化才有根基。你想想看,如果连瓶颈在哪一层的都不知道,谈什么优化?