端到端延迟:RPC RTT 不能解释动作为什么慢
自动关联目录:端到端延迟:RPC RTT 不能解释动作为什么慢
核心判断:玩家感知的是“输入到首个可见反馈”,网络 RTT 只覆盖其中一段;没有贯穿输入、权威提交和表现物化的动作身份,就只能知道慢,不能知道慢在哪里。
一、业务冲突
一次交互可能经历输入采样、候选判定、本地预测、网络排队、DS 校验与执行、复制接收、状态应用、动画/UI/音频调度,最后才在渲染帧中可见。RTT 正常时,主线程排队、DS 帧预算、资产等待或表现提交仍可能让动作迟钝;平均耗时又会掩盖偶发长尾。
二、实际实现
现有诊断已经解决了一部分基础问题。网络捕获按 Capture Generation 隔离,记录 World、Driver、Connection、方向、阶段、路由、分类、字节、数量、拒绝原因和队列年龄;记录时不依赖“当前 World”,因此 World 切换后不会把旧包记到新会话。捕获、队列和导出均有边界,账本还能保留最老入队时间。
耗时较重的物化流程也有独立阶段剖析,能按 World 和请求世代观察解码、创建与提交。但两个诊断面尚未用同一个动作身份贯通。
三、值得保留
诊断记录携带发生时的上下文,而不是导出时再猜上下文,这是跨 World 系统必须保留的设计。队列年龄比仅看吞吐更有价值,Generation 则防止一次捕获污染下一次捕获。
四、结构性缺陷
网络统计、运行时物化和表现剖析仍是多个诊断孤岛。没有 ActionId 时,无法回答某次按键对应哪条命令、哪次 DS Commit、哪份快照和哪一帧表现;只有阶段总耗时,也无法区分“工作本身慢”和“在队列里等得久”。跨进程时间戳若直接比较本地 Now,结论还可能被时钟偏移污染。
五、目标设计
让一次业务动作携带轻量 TraceContext,并把每段等待与执行分开:
struct ActionTrace {
ActionId id;
SessionEpoch session;
WorldGeneration world;
ConnectionId connection;
PredictionKey prediction;
};
Span(inputSample, localPrediction);
Span(commandQueued, commandSent);
Span(serverReceived, authorityCommitted);
Span(snapshotReceived, stateApplied);
Span(presentationQueued, firstVisibleFrame);同进程持续时间使用单调时钟;跨进程关联使用共享时钟映射,并携带估计不确定度。不确定度大于被测区间时,只报告本地分段,不伪造跨端精确值。
最终分别观察输入到预测、命令上行、DS 排队与执行、提交到状态、状态到首帧,以及预测纠偏,而不是只输出一个“总延迟”。
六、取舍与验证
全量追踪会增加热路径写入和隐私成本,应采用有界缓冲、采样、字段白名单和动态开关。验证要人工注入已知排队、网络延迟、资产等待和渲染阻塞,确认慢段能被定位;同时覆盖事件丢失、重复、乱序、World 切换和 Trace 截断。真正的验收标准不是日志更丰富,而是一次长尾能落到一个可负责、可复现的阶段。