DeepSeek Harness plugin

dsh-large-proj-perf

DSH 大会话性能插件:零拷贝 fork + fast initFor + 投影分片预热 + fork 缓存回填 + 分片 materialize + 冷会话 LRU 裁剪 + heap 检测(DeepSeek Harness / DSH)

Jump to install

Source facts

Repository
orangeofcarl0-sys/dsh-large-proj-perf
Latest update
Aug 21, 2026
Category
Memory
GitHub stars
1
Format
plugin
Catalog evidence
Upstream dsh.bundle evidence
Evidence path
package.json#dsh.bundle
Checked against
0.1.0-rc.8
Upstream check date
2026-08-20

This evidence comes from the upstream catalog. This site has not installed, run, or security-reviewed the plugin.

Install

Start with a prompt that asks an agent to review the GitHub repository and source. Switch to the command if you want to install it yourself.

Copy this prompt into DSH, Codex, or another agent and ask it to review the GitHub repository and source first.

Do not install or run any commands yet. Read this plugin's GitHub repository, README, and relevant source code. Then answer the questions below clearly and directly so I can decide whether it fits my needs:

1. What is this plugin, and what problem does it solve?
2. Who is it for, and what are its typical use cases?
3. How is it used after installation? Include one minimal example.
4. What known limitations or privacy, security, compatibility, or maintenance risks does it have?
5. Give a clear recommendation: recommend, conditionally recommend, or do not recommend, with reasons.

Distinguish statements documented by the repository, inferences from source code, and unknowns. If evidence is insufficient, say so explicitly. Do not guess or simply repeat the README.

GitHub: https://github.com/orangeofcarl0-sys/dsh-large-proj-perf
Plugin: dsh-large-proj-perf
Author: orangeofcarl0-sys

Check the source files

Read the README and other files from this plugin directory before installing.

File explorer3 files
README.mdSource · read only

dsh-large-proj-perf

![Version]() ![dsh]() ![License: MIT](LICENSE)

DSH(DeepSeek Harness)大会话性能插件:零拷贝 fork、投影分片预热、分片 materialize, 一次装齐,消除 fork/历史加载对超大会话的事件循环阻塞。

> ⚠️ 版本兼容性警告:本插件通过 monkey-patch dsh 内部方法实现(SessionStore.fork、 > PersistenceCoordinator.initForJsonlSessionPersistence.encodeMaterialization、 > SessionPreparations 等),与 dsh 版本高度耦合,当前针对 0.1.0-rc.6 / rc.7 / rc.8 > / 0.1.1-rc.1 开发并验证(rc.7 逐一核对无结构变化;rc.8 仅一处变更且是上游原生 > 实现了插件的 fastInitFor 优化——initFor 的 seed 从 structuredClone 深拷贝改为 > 直接引用 session.events,插件该补丁在 rc.8 起预期退役0.1.1-rc.1 发布说明 > 无插件相关改动,结构断言与全套测试全过)。 > dsh 升级后这些内部方法签名可能变化——所有补丁都带源码特征校验,不匹配时自动跳过 > 优化并回退官方行为(不会导致崩溃),但优化会静默失效。 > > 运行时版本探针:插件启动时自动探测 dsh 实际版本——已知版本(rc.6/rc.7/rc.8/0.1.1-rc.1)打 > dsh version: x.y.z (verified),列表外版本打告警并提示跑 tests/verify_compat.mjs。 > 版本也经 stats.get 暴露(value.dshVersion)。升级 dsh 后请确认启动日志无告警 > 与 signature mismatch,必要时重新适配本插件。

> ⚠️ 能力边界(重要):本插件只能缓解超大对话的性能/内存问题(分片、零拷贝、 > LRU 裁剪、预热等),无法彻底解决。根本原因在 dsh 的架构——live 会话事件树全量 > 驻留内存(每个超大会话 ~700MB)、历史加载全量解码 + 逐事件深拷贝。这些是上游架构 > 问题,插件 monkey-patch 触及不到。真正的根治依赖 dsh 上游支持事件分页加载/按需驻留, > 或主动控制会话规模(见下文「避免超长对话」)。

问题

dsh 0.1.0-rc.6 在大会话(数十万事件)上存在三类同步阻塞,导致 fork 卡顿、 历史加载报 signal timed out (internal)、严重时 OOM:

问题环节实测
A. fork 深拷贝Session 构造器逐事件 snapshotJsonValue(纯 JS 深拷贝)+ persistence initForstructuredClone(seed)18.2MB/20k 事件合计 ~480ms 同步阻塞(rc.8 已原生消除其中 initFor 那次,构造器深拷贝仍在)
B. projection 冷折叠SessionProjectionRegistry.cellFor() 冷时同步 buildCell 全量折叠74 万事件冷折叠阻塞 20+ 分钟(100% 单核)
C. fork 全量序列化fork 子会话首次落盘 encodeMaterializationeventLines = map(JSON.stringify).join("\n") 一次性序列化整个 seed60 万事件 = 501MB 单字符串;74 万事件直接 RangeError: Invalid string length

为什么「单个会话没事、fork 后出事」:普通会话持久化走增量 appendLines (每次序列化几十个事件),而 fork 子会话是全新 id,走 materialize 全量序列化 整个 seed——这是唯一会一次性序列化整条日志的路径。

rc.7 / rc.8 上游修了什么(为什么根因仍在)

rc.7:「修复大历史消息分页栈溢出」(commit 5201b848,PR #1371)。 session.history 分页时用 Math.min(event.seq, ...sourceEventSeqs) 展开溯源数组—— 一条定稿的 assistant 消息可以通过 sourceEventSeqs 引用数十万个流式分片, 展开超出 JS 引擎函数参数上限(~65535),历史分页请求直接 HTTP 500。修复改为循环 逐项扫描取最小 seq(复杂度仍线性),分页语义不变。上游问题笔记明确声明「本决策 不限制历史记录页面的字节大小,也不限制浏览器回放该页面的开销」——这是 api-proxy 层对已全量解码事件列表的切片逻辑,历史加载全量解码 + 逐事件深拷贝、live 事件树 全量驻留等根因一个都没碰。

rc.8:「改善大历史会话执行分叉操作上的性能耗时」——落实在 PersistenceCoordinator.initFor:seed 从 session.events.map((e) => structuredClone(e)) 改为直接引用 session.events上游原生实现了本插件的 fastInitFor 优化,连插件 补丁的 slice() 都比它多一次拷贝)。另「改善 SQLite 后端读写与分叉性能并降低存储 体积,数据结构不兼容」在 dsh-session-query-sqlite(插件不涉及 SQLite 后端,无影响)。 注意:这只消除了 A 类的一半——fork 流程的两个深拷贝里,initFor 那次被上游 原生消除(fastInitFor 补丁退役),但 fork 构造器逐事件的 snapshotJsonValue 深拷贝 仍在(rc.8 源码核实),它正是 zeroCopyFork 补丁走 fromRestore 通道绕过的核心, 在 rc.8 上仍然必要。B/C 类(投影冷折叠、fork 全量序列化)与历史加载的根因同样仍在, 插件继续兜底。

两版修复都是「可用性 / 单一热点」层面,未触碰架构根因:历史加载仍是 zstd 全量解码 + 逐事件深拷贝,live 会话事件树仍全量驻留(~700MB/会话)。根治仍依赖上游做事件 流式解码与按需驻留(另见「能力边界」与「避免超长对话」)。

方案

1. 零拷贝 forkzeroCopyFork,A):fork 的 seed 事件本就是 deepFreeze 不可变纯 JSON 树。补丁改走 Session.prepare(..., { seedSource: 'persistence' })fromRestore 通道——原地冻结复用引用,跳过整树深拷贝(346ms → 19ms)。 子会话 header(parentSession/seedLength/cwd)与官方 fork 逐字段一致。 rc.8 起仍必要:上游只原生消除了 initFor 那次拷贝,fork 构造器的 snapshotJsonValue 深拷贝依旧存在(rc.8 源码核实)。 2. fast init-forfastInitFor,A):PersistenceCoordinator.initFor 里那次 structuredClone(seed) 替换为冻结引用复用(135ms → ~0ms)。带 rc.6 源码特征 校验(structuredClone(e) 标记),内部结构不匹配时自动跳过并告警。rc.8 起上游 已原生实现(const seed = session.events),补丁预期退役——特征缺失但检测到 上游零拷贝形态时打 info 说明,不再误报漂移。 3. 投影分片预热warmupEnabled,B):会话进入(created/resume)且事件数超过 阈值时,抢在首次同步冷折叠前,分片重放 cells——每 chunkSize 个事件 setImmediate 让出事件循环,折叠完成后直写 registration.cells(WeakMap), 此后 snapshot()/drive() 全部命中热 cell。可用时从投影缓存行取基线跳过已折叠 前缀。实测 74 万事件:冷折叠 20 分钟 → 预热 200ms。 4. fork 缓存回填(B,随预热自动执行):fork 子会话(header.parentSession 存在) 预热完成后立即 cache.write(child) 建立投影缓存行——否则它被放弃时永远没有 缓存行,下次打开历史 coldSnapshotreadFrom(0) 全量读。 5. 分片 materializechunkedMaterialize,C):encodeMaterializationmaterializeChunkEvents 个事件一个 zstd frame(多帧是 dsh 解码端 scanZstdFrames 的原生格式,字节兼容),消除单巨字符串与 RangeError。 6. 冷会话补行backfillOnBoot,B 辅助,默认关):磁盘缺缓存行的大会话流式 补写。默认关的原因:readRaw 的 zstd 全量解码是同步的、插件层不可分片, 大文件仍会冻结事件循环数秒~数十秒。 7. 冷会话 LRU 裁剪preparedCacheTrim/preparedCacheSize,D):persistence 的冷会话 LRU 默认缓存 5 个完整事件树(每个大会话 ~700MB,5×700MB 叠加是 OOM 主因之一)。插件运行时把容量降到 preparedCacheSize(默认 1)并淘汰最旧的 ready 条目,主动释放冷会话事件树——省 ~2.8GB。无需手动改 cordis.patch.ymlconfig.set 运行时改这两个键即时生效;dispose 恢复原 capacity(已淘汰条目 不复活)。 8. heap 上限检测heapWarnBytes,D):--max-old-space-size 是 V8 启动期 参数、进程内改不了。插件检测 heap 上限低于阈值(默认 6GB)时告警,并引导用 scripts/start-dsh.ps1(内置 --max-old-space-size=8192)重启。

安全性

  • 共享引用等价于深拷贝:事件在进入源会话时已通过完整 JSON 边界与 surface 验证并

深冻结,任何代码都无法修改。

  • 所有补丁带 rc.6 源码特征校验,内部结构不符自动跳过并告警,绝不盲补。
  • 三层回退:(a) 调用时能力探测缺失 → 官方实现;(b) 补丁内运行时异常 → try/catch

回退官方实现;(c) 配置开关 → 永远官方路径。

  • dispose 完整还原所有补丁(冷会话 LRU 裁剪恢复 capacity 原值,已淘汰的缓存

条目不复活)。

安装

# 从 GitHub 安装(推荐)
dsh plugin --profile web add github:orangeofcarl0-sys/dsh-large-proj-perf
# 或
dsh plugin --profile web add https://github.com/orangeofcarl0-sys/dsh-large-proj-perf

# 本地开发
dsh plugin --profile web add file:<本仓库路径>

> 注意:每次修改仓库代码后,需把 lib/cordis.patch.ymlpackage.json > 同步到 <DSH_HOME>/profiles/web/node_modules/dsh-large-proj-perf/file: 安装 > 不会自动跟随源文件更新),或重新执行 dsh plugin add

重启 dsh web 生效。日志出现 [dsh-perf] installed (...) 即成功。

> 环境要求:Node ≥ 22.15.0node:zlib 的 zstd 接口所需,低版本加载插件 > 会直接失败)。package.json 已声明 engines

大会话内存(推荐启动方式)

多个超大会话(数十万事件)的 live 事件树每个 ~700MB,默认 V8 heap 上限 ~4GB 会让 dsh 在内存叠加时 OOM。插件已自动做冷会话 LRU 裁剪(省 ~2.8GB),但 heap 上限是 V8 启动期参数、进程内改不了,推荐用仓库自带脚本启动:

powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\start-dsh.ps1

它等价于 node --max-old-space-size=8192 .../dsh/lib/bin.js web(停止旧进程 → 重启 → 打开浏览器)。若不使用该脚本,插件启动时会打 V8 heap limit ... < ... 告警提醒你加参数。

避免超长对话(主动规避)

本插件做的是「被动优化」——把 fork/历史加载/落盘的大会话阻塞降下来,但无法削减 正在使用的 live 会话事件树(每个 ~700MB,dsh 架构决定全量驻留)。要从根上避免 超长对话的内存/卡顿,推荐配套使用:

输入 /fresh 一键「总结当前对话 → 开启新对话 → 归档老对话」。在一个会话工作 一段时间后用它归档,释放 live 事件树内存,而不是让会话无限增长到 70 万+ 事件。

dsh plugin --profile web add github:orangeofcarl0-sys/dsh-fresh-start

两者配合:dsh-large-proj-perf 兜底性能,dsh-fresh-start 主动控制会话规模。

API

POST http://127.0.0.1:3080/dsh-large-proj-perf/api/<method>

  • stats.get — dsh 版本探针(dshVersion)、fork 次数/零拷贝占比/回退、

预热计数、补行计数、最近记录

  • stats.reset — 清零
  • config.get / config.set — 运行时开关,config.set 同时写 settings 持久化;

数值项带下限钳制(如 materializeChunkEvents ≥ 1000chunkSize ≥ 1), 非法值(类型不符/NaN/低于下限取下限)被拒绝或收敛,不会进入危险区间

curl -X POST http://127.0.0.1:3080/dsh-large-proj-perf/api/stats.get
curl -X POST http://127.0.0.1:3080/dsh-large-proj-perf/api/config.set \
  -d '{"zeroCopyFork": false}'

验证

测试依赖真实的 dsh 内部包(@deepseek-ai/dsh-session 等),它们不在本仓库依赖里, 而是全局 dsh 安装的嵌套依赖,Node 解析不到。先链接再跑:

powershell -NoProfile -ExecutionPolicy Bypass -File .\scripts\link-deps.ps1
npm test   # 或单独跑:node tests/smoke_fork.mjs
  • tests/smoke_fork.mjs(17 断言):官方 fork 基线 / 零拷贝 fork 功能等价 /

header 平价(含 origin 不继承)/ seed 前缀逐字节等价 / dispose 还原 / 版本漂移回退 —— ALL PASS

  • tests/test_fast_initfor.mjs(10 断言):initFor 补丁安装 / 源码特征漂移跳过 /

无 persistence 服务存活 / rc.8 上游原生零拷贝形态 → 补丁预期退役(不误报)—— ALL PASS

  • tests/smoke_warmup.mjs(11 断言):分片预热与同步折叠一致 / checkpoint 基线 /

并发 drive 让位 / dispose 中止 —— ALL PASS

  • tests/test_backfill.mjs(8 断言):fork 回填 / 磁盘冷会话补行 —— ALL PASS
  • tests/test_chunked_materialize.mjs(5 断言):分片多帧解码等价 / 阈值不变 —— ALL PASS
  • tests/test_cache_trim.mjs(18 断言):LRU 裁剪 / dispose 恢复 capacity / 运行时

开关 / config.set 数值钳制 / 版本探针(stats.get 暴露 dshVersion)—— ALL PASS

  • tests/verify_compat.mjs(16 断言):对真实安装的 dsh 源码做特征断言——

fork/initFor/encodeMaterialization/toHeaderLine 字段集/SessionPreparations/ 投影注册表与缓存接口/packChunkRuns 导出;版本不在已知列表时打 WARN

局限

  • 版本高度耦合(重要):补丁绑定 dsh 内部结构(_forkSeed

initFor/encodeMaterialization 源码特征、SessionPreparations.capacity 等)。 已在 0.1.0-rc.6 / rc.7 / rc.8 / 0.1.1-rc.1 上验证;dsh 升级后,特征校验会自动跳过优化并 回退官方行为(不崩溃、不误补),但优化会静默失效——升级后务必跑 node tests/verify_compat.mjs(或确认启动日志无 signature mismatch),并按需 重新适配。本插件不适合在 dsh 版本频繁变动时依赖其优化。

  • enqueue 的逐事件 structuredClone(fork 第三次拷贝)在插件层无法安全消除——

它在 write-behind 闭包内部,且承担"persistence 独立于生产者"的所有权语义。根治需 上游改为按需快照。

  • 冷会话 coldSnapshot 的全量 readFrom(0)(zstd 解码 + 逐事件

snapshotStoredEvents 深拷贝)无法在插件层安全分片——readRaw 的同步解码是硬伤。 根治需上游把 readFromCore/loadStored 改成分片让出事件循环。

  • 超大会话(70 万+ 事件)加载本身有内存 OOM 风险,与插件无关;建议配合

dsh-fresh-start 主动归档。