性能与延迟
读完这页你能做到三件事:
- 用
/perf看清这次会话的时间花在哪一段 - 用
/perf --days 7判断本机最近是变快还是变慢 - 看懂每个数的口径,不被均值和跨模型汇总骗到
所有数据都在本机:会话轨迹在 ~/.sid-code/trajectories/sessions/,跨会话索引在 ~/.sid-code/session-index.jsonl(看单会话时还会读同目录下的 usage-ledger.jsonl 核对成本)。 /perf 只读这些本地文件,不联网。数据流向见隐私与数据流向。
快速上手
会话里打 /perf:
性能 · 本会话 20261014-160154-7fbf9547
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
首字延迟 TTFT P50 1.8s P95 4.2s (n=12)
生成耗时 P95 21s (n=12,响应头→流结束,单次请求)
生成速度 42 tok/s
端到端 P50 18s P95 51s (n=5,回车→最终答复)
时间花在哪 模型 78% (151s) / 工具 22% (41s)
上下文峰值 62%(124k tokens)示例中的数字是示意值。当前会话的轨迹还没落盘时,
/perf会改看最近一次会话并提示你。
四个视图
| 用法 | 回答什么 | 数据源 |
|---|---|---|
/perf | 这次会话慢在哪一段 | 当前会话轨迹 |
/perf <id|latest> | 指定的历史会话 | 该会话轨迹 |
/perf --days N | 近 N 天比前 N 天变快还是变慢 | session-index.jsonl |
/perf --by-version | 每个版本的延迟(最近 10 个) | session-index.jsonl |
任一视图加 --json 输出机器可读结果,方便接脚本或自己的看板。
跨会话视图读索引而不是轨迹目录:轨迹会被自动清理,索引不会,所以几周前的会话照样进趋势 (索引只有显式执行 /trace --prune-index N 才会裁剪)。
每个数是什么
| 指标 | 口径 | 取数源 |
|---|---|---|
| 首字延迟 TTFT | 发出请求到收到第一个任意内容(含思考、工具调用),每次请求单独计,不跨重试累加 | StreamPhase(first_content).ttft_ms |
| TTFB | 发出请求到收到响应头 | StreamPhase(headers_received).ttfb_ms |
| 生成耗时 | 单次请求从收到响应头到流结束,不含重试 | RetryTelemetry(stream_completed).elapsedMs |
| 生成速度 | 输出 token ÷ 生成耗时累计 | 轨迹 output_tokens_per_sec |
| 端到端 | 你按回车到最终答复,含等你确认权限的时间 | TurnComplete.elapsed_ms_since_prompt |
| 时间花在哪 | 模型整轮耗时累计 vs 工具执行墙钟累计 | AfterModelRaw.elapsed_ms / PostToolUse.duration_ms |
| 上下文峰值 | 本会话最高一轮的上下文占用 ÷ 模型窗口 | 轨迹 context_usage_peak_ratio |
TTFT 只认可视文本会出错:思考型模型和纯工具调用轮会被系统性高估几十秒。这也是它必须按「首个任意内容」算的原因。
生成耗时从收到响应头开始算。有的网关要等模型开始出字才回响应头,这时大部分等待都落在 TTFT 里,生成耗时会比 TTFT 小很多。这是口径,不是算错。
怎么判断慢在哪
- TTFT 高:模型排队或网关慢。用
/trace --health看是不是某个 provider 整体在变慢,必要时换模型或路由。 - TTFT 正常但生成耗时长、tok/s 低:模型生成本身慢,或者输出太长。
- 工具占比高:慢在命令或工具(测试、构建、搜索)。用
/trace看具体是哪次调用。 - 端到端高但前三项都正常:多半是轮数多。看
/perf --days里的「轮数/会话」,或者等权限确认花了时间。 - 上下文峰值超过 65%:会话太长,后面每一轮都更慢也更贵。该
/compact或新开会话,见上下文与压缩。
为什么延迟类指标只报 P50 / P95
均值会被大多数正常请求稀释,掩盖掉那几次让你等半分钟的慢请求,而慢尾巴恰恰是体感最差的部分。所以延迟类指标(TTFT、生成耗时、端到端)只给分位数,并在每个数后面标样本量 n;生成速度和上下文峰值是整段会话的单值,不带 n。
样本量很重要。单会话的 TTFT 往往只有十几个样本,n=3 的 P95 基本就是最大值。--days 视图里,两侧都至少有 5 个样本才会判「改善」或「变差」;样本不够显示「样本不足」,样本够但变化不到 10% 显示 ≈。
跨会话的 P95 是「每会话 P95 的 P95」。分位数不能求平均:P50 的平均不是平均的 P50。
为什么不同模型的 TTFB 不能放在一起比
同一个底层模型走不同网关路由,TTFB 的含义可能完全不同:一条路由在模型开始出字时才回响应头,另一条路由在接单时就先回响应头。
一次实测里,同一个模型的两条路由,(TTFT − TTFB) ÷ TTFT 的中位数分别是 87% 和 5%。把它们汇总出来的 TTFB 不描述其中任何一条,却会让人得出「首字节很快」的结论。
所以 /perf 只在单个模型内展示 TTFB,跨会话趋势里 TTFT 也单独列出按模型的那几行。混用多个模型时,以按模型的数为准。
趋势怎么读
性能趋势 · 近 7 天 vs 前 7 天
会话数:本期 48 / 上期 62(不含还在跑或崩溃未收尾的会话;中断、报错收尾的仍计入)
指标 本期 上期 变化
TTFT P50 5.7s (n=13) 2.2s (n=57) ▲ 158% 变差 ⚠
生成速度 P50 无样本 无样本 样本不足
...▲/▼是数值方向,「改善 / 变差」才是好坏。延迟变小是改善,tok/s 变大是改善。- 变化不到 10% 记
≈;退步达到 20% 标⚠。 - 「无样本」表示这段时间的会话没有这项数据,不是 0。比如生成速度和工具耗时是新版本才开始写进索引的,旧会话一律无样本。
- 「会话数」只排除没跑到收尾的增量会话(
exit_status=incomplete,进程崩溃或还在跑)。用户中断(Esc、Ctrl-C、外部 kill)、报错收尾、达到 maxTurns 或预算上限的会话仍计入——它们是真实样本,排除会让延迟分位数系统性偏低。 - 成本只统计已计价的会话。网关没回价格的会话成本记为 0,混进来会把中位数压成 $0,看起来像「省了 100%」。
- 先看会话数和
n。模型组合变了(比如这周多用了思考型模型),TTFT 变差可能只是换了模型,按模型那几行能分清。
还没有的
- TPOT / token 间隔:决定打字流畅感,目前没有采集。
- 自动告警:趋势需要你主动打
/perf --days查看,不会自己推送。