Repository navigation
Open
Labels
Description
性能可观测系统(实时收集 + Web 面板 + 全量/夜间 CI 门禁)
跟踪单。背景:近期所有性能事故(#5403 OOM×6、#4528 slow-session、#5385 cache 钉前缀、#5449 孤儿进程 51% CPU)全部由用户先发现,CI 零预警。目标=让性能回归在代码合并前可见、跨版本可对比、30 秒可复现。owner 已确认方向与约束(2026-11-01)。
硬约束(owner 拍板)
- 元数据只进 SQLite/数据库模式(现有 unified store 连接,新表);不再用 JSON 文件存。
- 纯 JSON 存储模式冻结/废弃:不新增任何维护,本系统对其零埋点;废弃收尾(迁移指引、legacy-only 降级路径的告警化)另立子任务(关联 Known-but-wedged same-lane peer: replacement loses unified storage for its whole life and the panel misclassifies the stuck instance | 已知但卡死的同车道实例:接替实例整个生命周期丢失统一存储,面板状态误导 #5451)。
- Web 面板必须有性能观测页(不是可选)。
- CI:普通(PR)CI 一律不跑 perf;全量(FULL)CI 跑;夜间定时也跑。复用既有 FULL 触发机制,不自造新触发。
L1 实时采集(只写库,零新依赖)
- 统一存储打开时初始化新表(perf 事件):按请求一行——lane、wire 形状(openai/anthropic/responses/google/native)、模式(pure-proxy/plugin-dsh/pi-opencode/acp-panel)、msgs、inboundBytes、parseMs / prepMs(新增实测,[Bug][dsh] Plugin lane performs a full re-parse and resends the entire body every round (81 MiB → hundreds of MB AST), w | [Bug][dsh] plugin 车道每轮全量解析重发 body(81 MiB→数百 MB AST)是 #5403 OOM 的生产者:用水位线断言替换逐条复核,服务端只解析新增尾段 #5418 指的两个卡口)、foldGateDeferred?、residentAstBytes、outboundBytes、上游 usage 的 cached_tokens→缓存命中率、queueWaitMs;内存采样行(kind=mem)每 N 秒一条(memoryStats + 最大会话 AST 字节估计)。
- 批量写(WAL,batch flush),写失败降级为内存环+一次性 warn(沿用 [PR] Repeated invocation guard: on the 5th occurrence, warn only without killing the turn; terminate on the next violation (# | 重复调用守卫:第 5 次只警告不杀回合,再犯一次才终止 (#5225) #5327 store adopt 纪律:不因遥测丢数据也不炸请求路径)。
- 进程内同时保留环形缓冲供
/stats(见 L4)。
L2 场景夹具(每个角落,确定性种子)
生成器提交、大数据不入库:gen-perf-fixture --seed K --msgs N --shape X:S-small(50)/S-med(2k)/S-large(2万条≈80MiB,复刻 #5403 形状)× 形状变体 × 折叠状态(未折叠/折一半/闸门卡死态)× 行为脚本(追加/频繁 Esc/压缩密集/冷重启 churn/Windows EPERM 模拟)。纯合成数据,零隐私面。
L3 bili bench + 基线 ratchet(只在 FULL/夜间跑)
bili bench <scenario>:起真实 server(XDG/端口隔离,复用 e2e-dsh hermetic 手法)→ 吃库出报告(p50/p95/HWM/命中率/闸门推迟次数)→--baseline x.json相对容差带判回归(3 轮中位数抗抖动)。- 基线文件进仓库 + 重生成脚本 + 守卫(金样同构文化:合法改变性能的 PR 必须带说明更新基线);抖动指标隔离名单观察后再入门禁。
- 覆盖矩阵:模式(dsh 插件全量重发/pure-proxy/多会话并发/中断密集/压缩密集/Windows 冷重启)× 形状 × 存储后端(sqlite/mysql)× 开关(timestamps/fastpath/lazy-store)。PR 级 0 个 perf job。
L4 观测面
/stats扩展现有 health JSON:会话数、各车道 p95、最近折叠闸门推迟、存储模式(unified/legacy)——远程诊断一条 curl。- Web 面板 Perf 页(必须):按版本/车道 sparkline(p95 prep、缓存命中、内存水位、OOM/OOM-pre 窗口计数)。
- 外部看门狗:launcher 侧 OS 级采样目标 pid RSS/CPU → 孤儿高 CPU([Bug] 0.1.209 dsh/Windows: an orphaned proxy outlives its dead owner (33 min, ~51% CPU, write lock held) and is never reaped → the replacement drifts 18789→18790 while the caller stalls 826 s with 0 bytes #5449 型)变告警。
路线图(自包含 PR)
- P1 库表 + 四卡口埋点(parse/prep/发送)+ 内存采样 + 环形缓冲(schema 稳定性测试)← 开工
- P2 夹具生成器 +
bili bench(只记录不判)+ artifact 上传,静默收一周噪声底 - P3 容差带 + ratchet 基线 + FULL/夜间矩阵接线
- P4
/stats+ 面板 Perf 页 + 外部看门狗 - P5 趋势图/告警阈值化;缓存命中率趋势反哺 Long Claude Code session re-caches ~140-175K tokens per turn (cache read stuck at the fixed prefix) #5385
Activity
ranxianglei commentedon Nov 1, 2026
P1 已交付:PR 见上条链接(分支 perf/l1-sqlite-telemetry)。落库=每请求一行+30s 内存采样,WAL+200k 行保留窗;JSON 模式冻结零足迹;写失败只停采集不碰服务。P2(夹具+bili bench)下一步。
fix: #5460 route perf-telemetry degrade warnings through the tee logger
docs: #5460 register BILI_PERF_TELEMETRY in CONFIGURATION.md (en+zh)
fix(perf): #5460 review — pure-JSON (legacy) storage mode stays froze…
fix(perf): #5460 review — enforce the one-shot degrade contract on op…
fix(perf): #5460 review — synchronous=NORMAL for perf.sqlite (hot-pat…
refactor(perf): #5460 review — compute outbound byte length once in l…
test(perf): #5460 review — pin the 200k-row retention cap end-to-end
test(perf): #5460 review — correct retention expectation to the sweep…
fix(perf): #5460 resolve the SQLite engine through the shared storage…
ranxianglei commentedon Nov 1, 2026
(ai: vllm/qwen3.8-27b)
P2 已交付:PR #5477(分支
perf/l2-bench-fixtures,stacked on #5461,P1 先合)。另外在 P1 分支上顺手修了一个评审发现的启动级缺陷(commit f05e6e8,已推到perf/l1-sqlite-telemetry,归 #5461)。标签:scope/storage + p3(主载体是 perf.sqlite 遥测存储与基准工具面,面板/CI 门禁是同系统消费端;p3=增强项,无用户侧破坏)。
查重:不重复——本单即跟踪单自身路线图的既定步骤,无平行条目。
八问
import "node:sqlite"——该内置模块 Node ≥22.5 才有,而 package.json 仍声明 engines >=20,静态导入让整个 CLI 在老 Node 上模块加载期崩溃(不可用的是全部 bili,不只是遥测),且会挂 dist 自包含门禁。openSqliteDatabase:builtin node:sqlite → 宿主 better-sqlite3 → 自下载,彻底解决 dsh/pnpm 构建脚本门导致 build-blocked:SQLite 引擎自举(内置优先 → 运行时自下载 → 复用宿主) #2833/feat: SQLite engine self-bootstrap — builtin -> host -> cached -> self-download (#2833) #2845),零新增外部依赖,全缺时按既有契约一次性警告、只降级停用遥测。C2/C3:bili fixture-gen(参数当纯函数,同 seed 字节级相同,内容带哨兵值/doc# 引用保证压缩触发时摘要仍确定;S-small 50/S-med 2k/S-large 2万条≈80MiB 复刻 [Bug][dsh] 20k-message / 81 MiB-inbound session: host aborted 6× in 2 h — the #3050 resident-AST OOM is not bounded bysessions.hardMaxBytes(Windows, 0.1.210) #5403 形状)+bili bench <scenario>(一次性 XDG 目录+随机端口拉起真代理,进程内确定性假上游双 wire,按 dsh 插件车道全量重发形状逐回合回放,结束后读子进程 perf.sqlite 出 p50/p95/max/mean+进出站字节+内存 HWM 的 JSON 工件;只记录不判——指标再慢也 exit 0,只有 harness 失败才 exit 1)。gen-perf-fixture落成bili fixture-gen子命令(单 bin 打包形态,零打包变更,随 dist/index.js 发布);②折叠状态轴(未折叠/折一半/闸门卡死)与频繁 Esc/冷重启 churn 行为脚本留待 P3 矩阵——真正预置折叠态需要持久化状态注入,不在 P2「只记录」范围内硬造。--seed/--msgs/--shape/--out/--rounds/--keep-workdir/--dist),无新 env、无新 config 字段(BILI_PERF_TELEMETRY属 P1 面)。验证(本地定向,全量交 CI):typecheck+build(含 dist 门禁)绿;tests/issue5460-perf-bench.test.ts 9/9 + 门控 e2e smoke 1/1;P1 套件 20/20;cli-parseargs 7/7。实测
bili bench proxy-append-openai-s-small:50 回合 0 失败,req_rows=50,total_ms p50=5ms p95=9ms(max 2725ms=首轮冷启动),进站 5.3MB。判定:P2 交付完毕,PR #5477 等 CI 结果;合并顺序 #5461 先行、#5477 跟进(P1 合入后本 PR 的有效增量即 feat+test 两个 commit)。噪声底静默收集一周后进入 P3(容差带+ratchet+FULL/夜间接线)。
22 remaining items
fix: #5460 route perf-telemetry degrade warnings through the tee logger
fix(perf): #5460 review — pure-JSON (legacy) storage mode stays froze…
fix(perf): #5460 review — enforce the one-shot degrade contract on op…
fix(perf): #5460 review — synchronous=NORMAL for perf.sqlite (hot-pat…
refactor(perf): #5460 review — compute outbound byte length once in l…
test(perf): #5460 review — pin the 200k-row retention cap end-to-end
test(perf): #5460 review — correct retention expectation to the sweep…
fix(perf): #5460 resolve the SQLite engine through the shared storage…
docs(perf): register BILI_PERF_TELEMETRY in the config-docs seed so t…
test: pin BILI_PERF_TELEMETRY off suite-wide — Windows EBUSY on sandb…
test: actually ASSIGN the BILI_PERF_TELEMETRY suite pin (#5460 P1)
docs(perf): regenerate config docs from BILI_PERF_TELEMETRY seed afte…
test(perf): #5460 rebase — retarget logRequestCost import to src/serv…
chore: merge master ahead of #5460 P1 telemetry (conflict pass 2)
fix(perf): degrade telemetry instead of throwing on a non-serializabl…