orangeofcarl0-sys/dsh-large-proj-perf ↗★ 0
dsh-large-proj-perf
DSH 大会话性能插件:零拷贝 fork + fast initFor + 投影分片预热 + fork 缓存回填 + 分片 materialize(DeepSeek Harness / DSH)
安装
$
npx -p @deepseek-ai/dsh dsh plugin --profile web add github:orangeofcarl0-sys/dsh-large-proj-perf说明文档
阅读完整 README ↗dsh-large-proj-perf
DSH(DeepSeek Harness)大会话性能插件:零拷贝 fork、投影分片预热、分片 materialize, 一次装齐,消除 fork/历史加载对超大会话的事件循环阻塞。
问题
dsh 0.1.0-rc.6 在大会话(数十万事件)上存在三类同步阻塞,导致 fork 卡顿、
历史加载报 signal timed out (internal)、严重时 OOM:
| 问题 | 环节 | 实测 |
|---|---|---|
| A. fork 深拷贝 | Session 构造器逐事件 snapshotJsonValue(纯 JS 深拷贝)+ persistence initFor 的 structuredClone(seed) | 18.2MB/20k 事件合计 ~480ms 同步阻塞 |
| B. projection 冷折叠 | SessionProjectionRegistry.cellFor() 冷时同步 buildCell 全量折叠 | 74 万事件冷折叠阻塞 20+ 分钟(100% 单核) |
| C. fork 全量序列化 | fork 子会话首次落盘 encodeMaterialization → eventLines = map(JSON.stringify).join("\n") 一次性序列化整个 seed | 60 万事件 = 501MB 单字符串;74 万事件直接 RangeError: Invalid string length |
为什么「单个会话没事、fork 后出事」:普通会话持久化走增量 appendLines
(每次序列化几十个事件),而 fork 子会话是全新 id,走 materialize 全量序列化
整个 seed——这是唯一会一次性序列化整条日志的路径。
方案
- 零拷贝 fork(
zeroCopyFork,A):fork 的 seed 事件本就是deepFreeze不可变纯 JSON 树。补丁改走Session.prepare(..., { seedSource: 'persistence' })的fromRestore通道——原地冻结复用引用,跳过整树深拷贝(346ms → 19ms)。 子会话 header(parentSession/seedLength/cwd)与官方 fork 逐字段一致。 - fast init-for(
fastInitFor,A):PersistenceCoordinator.initFor里那次structuredClone(seed)替换为冻结引用复用(135ms → ~0ms)。带 rc.6 源码特征 校验(structuredClone(e)标记),内部结构不匹配时自动跳过并告警。 - 投影分片预热(
warmupEnabled,B):会话进入(created/resume)且事件数超过 阈值时,抢在首次同步冷折叠前,分片重放 cells——每chunkSize个事件setImmediate让出事件循环,折叠完成后直写registration.cells(WeakMap), 此后snapshot()/drive()全部命中热 cell。可用时从投影缓存行取基线跳过已折叠 前缀。实测 74 万事件:冷折叠 20 分钟 → 预热 200ms。