← 回到 infra 主页

← 上游 issue 专栏 · infra · DSH 上游缺陷材料

#19performancesession/list2026-10-19

session/list 重会话 119s–>200s 等待;cursor 字段未被使用(是否补分页待定)

DSH 0.2.1-rc.2 · package sha256 bea4288aa88e… · 单席位观测 · 2026-10-19 按 DSH 反馈修订

2026-10-19 DSH 反馈修正(本页已按此改写)

一句话(修订后):重会话账户上观测到 session/list 的分钟级等待(mch10 单次 119s;另一次 >200s 客户端超时)。cursor 字段当前没有调用方传入;补分页还是删字段待定。根因尚不能归到“读 79MB 日志”或“逐行 projection”;下一步应先做主线程阻塞/排队分段 profile,再决定分页、缓存、离主线程、compaction 哪些真正有效。

① 实测锚点

账户/场景session 数主会话session/list 观测结果
mch109779,106,108 B / 307 turns119,334 ms(全量闸一次);另一次客户端 >200s 未返回单次等待 / 超时,异常
mch25未逐项展开未逐项展开读超时 2 次 × 120,000 ms;累计 240,096 ms两次超时的累计,不是单次耗时
DSH CI 基准约 3,000—约 3s 列完(DSH 反馈;版本/存储/负载未对齐)只作参考,不能据此推断 97 行本应远低于此
全量闸 DSH_INVARIANTS——SESSION_LIST_HEALTH 30s24/25,唯一红项

证据:/home/infra/log/dsh-invariants-rc2-highcap-20261019.log;mch10 会话目录 /home/mch10/.dsh-alpha/sessions/。日志只保留判定行,不包含凭据或用户内容。

② 复现

在已认证的 DSH 实例上调用同一 RPC;时间以客户端 wall clock 计,服务端不做额外包装:

# 选择有大量 session 的账户(示例:mch10)
# 通过既有 gateway/CLI 发 session/list;不要带筛选,复现“全量列表”路径
session/list  { "_request": {} }

# 观测:轻账户 <1s;重账户 119s / >200s
# 健康探针等价命令(仓内):
sudo -n -u infra sudo -n python3 ops/dsh/check-dsh-invariants.py
# 失败行:SESSION_LIST_HEALTH_FAIL ... 119334 ms > 30000 ms(97 行)

复现时同时记录:session 数、主会话字节数、active turn、CPU/主线程占用、gateway 并发。单看“97 行”不够,必须带上“主会话 79MB / 307 turns”这个负载条件。

③ 已确认的 API 现状

相关既有材料:#12 控制面一元 RPC 主线程饥饿(已证明同一份约 0.5s CPU 的 session/list 可被拉到 34–45s)和 #8 spawn 阻塞探测(spawnSync 9.0% 阻塞)。本条补充的是 2026-10-19 的重会话/大列表案例,以及 cursor 字段当前无调用方传入、接口行为待评估,不重复 #12 的根因结论。

④ 根因假设(待 profile,不当作结论)

  1. H1 主线程被长 turn 阻塞:这是优先验证的假设,不是结论。CI 的 3000 行约 3s 与本机版本/存储/负载未对齐,不能推出“97 行本应远低于此”,也不能据此认定更可能是长 turn 阻塞。workSliceMs + scheduler.yield() 只能让出,不能缩短等待;需要分段计时。
  2. H2 列表 handler 内部某段慢:persistence 列举、header clone、投影缓存读取、编码,需要在空闲实例上单独计时。
  3. H3 投影缓存/大 header:列表读投影缓存;若缓存缺失或 header 很大,单行成本会升,但需要冷/热缓存对照。
  4. H4 网关/传输/客户端:需区分服务端 RPC 完成时间与客户端等待时间。

相关:#6161(仍 open;已合并的是相关优化,不是它本身)、#1757、#5379(主线程阻塞)。本机 rc.2 的 cherry-pick 范围未核实,不能把已有合并直接等同于本例已修。

建议的 profile(先量再改)

⑤ 影响

⑥ 候选方案与待评估目标

  1. cursor/limit:当前没有调用方传入;补分页还是删字段待评估。若补,注意“只在全量列举后切页”未必能解决首屏慢,首屏快路径需要单独设计。
  2. header-only 首屏:只返回 sessionId/updatedAt/running/title;projection 按需加载。
  3. 短 TTL 列表快照:同一秒并发请求复用一次组装;需验证不会返回过期状态。
  4. 离主线程/独立队列:仅当 profile 证明主线程排队是主因时采用;否则收益有限。
  5. 重会话 compaction/摘要:作为负载治理候选,不是本 issue 的前置条件。

待评估目标:首屏 p95 <1s、全量分页完成 <5s 是待评估目标,不是五项验收承诺;具体阈值需按 profile 后的实际队列/处理器成本评估。不得通过调大 30s 预算/白名单变绿。

⑦ 临时缓解

English summary (for upstream)

session/list was observed at 119s for a 97-session account, and another client call exceeded 200s; mch25 hit two 120s read timeouts (240s cumulative, not a single request). The cursor field exists in the request schema but no caller currently passes it; whether to implement pagination or remove the field is TBD, so it should not be written as “must add”. The list reads headers and projection caches, not a full 79MB log replay. The 3,000-session CI baseline (~3s) is not aligned with this host’s version/storage/load, so it cannot establish that 97 rows should be far below that, nor that long-turn main-thread queueing is the cause. Main-thread queueing is the priority hypothesis to verify. Please profile queue wait vs handler time, event-loop lag, and CPU before choosing fixes. Keep the 119s/>200s anomaly; treat pagination, off-main-thread, caching and compaction as candidates, and p95 <1s as a target to evaluate. Related: #6161 (still open; merged work is related optimization, not the issue itself), #1757, #5379.