前言¶
如果你用 DSH 跑过长会话,大概率遇到过这种情况:点开一个旧会话,要等上好几秒才有反应。问题出在存储层——DSH 的 JSONL 会话后端每次写入批处理都会单独压缩成一个 zstd 帧再追加到文件尾部,一个长会话动辄上万个帧;而读取时必须逐帧解压,后端又没有 seek 式后缀读取,无论只要尾部还是全部,都得解码整个文件。
帧数是历史写入定形的,事后无法自己收缩。kkishapppy/dsh-session-repacker 就是针对这个问题:把散落的万帧日志重打包成官方原生形态,实测最大会话打开耗时从约 661ms 降到约 126ms。
这是什么¶
dsh-session-repacker 是一个 DSH 插件(MIT 许可证,版本 0.1.0),由 kkishapppy 维护。它把 DSH JSONL 会话后端逐批写入产生的成千上万个独立 zstd 帧重打包为官方原生两帧形态:头部帧恰好一行 header,其余全部明文拼接后重压为单个事件帧。
两个关键点:
1、重打包后的明文逐字节不变。dsh 读取路径完全兼容,读取侧的 assertZstdHeaderFrame 只要求第一帧恰为一行 header,重打包结果满足这一要求。
2、插件只做维护,不改变任何读取 API 与数据语义。覆盖一切从磁盘读旧会话的路径:GUI 打开、新对话接续/分支、子会话继承。
效果数据¶
作者给出的实测结果:
| 对象 | 重打包前 | 重打包后 |
|---|---|---|
| 最大单个会话 | 14,467 帧 / 5.49MB / 约 661ms | 2 帧 / 2.09MB / 约 126ms(约 6 倍) |
| 全量 24 个旧会话 | 39,911 帧 / 20.08MB | 48 帧 / 10.67MB |
除了打开速度,压缩体积也约减半——单个大帧的压缩率远好于上万个独立小帧。
安装与启用¶
作为 DSH 插件安装(推荐):
dsh plugin --profile web add dsh-session-repacker
也可以克隆到 plugins/ 目录后 link 进 profile。如果要自己构建,在仓库目录执行:
npm i
npx -y tsdown@0.22.2 --config ./tsdown.config.ts
产物为 lib/index.mjs。
启用需要在 profiles/<profile>/cordis.patch.yml 里配置插件和参数:
- id: session-repacker
config:
root: 'E:\DeepSeekHarness\sessions' # 会话根目录(必填)
minFrames: 200 # 帧数低于此值不处理(默认 200)
minAgeMs: 600000 # mtime 距今不足此值不处理(默认 10 分钟)
intervalMs: 3600000 # 周期维护间隔毫秒(默认 1 小时)
重启服务器后生效:插件启动时做一次全量扫描,之后按 intervalMs 周期维护。root 是唯一必填项,其余三项都有默认值,不配也能跑。
独立 CLI¶
如果不想挂插件跑后台任务,仓库提供独立 CLI,不需要 DSH 服务:
node tools/repack.mjs <root> # 扫描并重打包
node tools/repack.mjs <root> --dry-run # 只统计不落盘
node tools/repack.mjs <root> --file <path> # 只处理指定文件(可多次)
node tools/repack.mjs <root> --min-frames 64 --min-age-ms 60000
建议先跑一次 --dry-run 看统计,确认范围和预期收益后再实际执行。--file 可以重复传入,适合只处理某几个重点会话;--min-frames 和 --min-age-ms 用于自定义阈值。
安全设计¶
重打包会替换磁盘上的会话文件,安全性是这个插件的着力点,措施包括:
1、只处理 .jsonl.zstd 文件,跳过 mtime 距今小于 minAgeMs 的文件,避开活跃写入。
2、跳过当前 live 会话。
3、替换前做字节级等价校验:新文件解压出的明文必须与原始明文完全一致。
4、替换前再次 stat 比对 size/mtime,如果文件在此期间被并发追加,放弃本次操作。
5、torn tail(未写完的帧)直接跳过,交给 dsh 自身的修复路径处理。
6、写入采用临时文件 + fsync + 原子 rename,Windows 下与官方后端同构。
另外,服务器对重打包后的文件追加新帧(如 session/end-seed 等)实测兼容,追加后的文件还可以被再次重打包,操作是幂等的。
适用场景与注意¶
适合的场景:会话历史长、打开慢,且旧会话帧数已经定形无法自行收缩的部署。配合后台周期维护,可以让这件事自动化。
几个注意点:
- 已产生的旧文件帧数定形后无法回溯压缩,只能靠本插件或 CLI 重打包。如果想让未来日志少产生帧,可以调大
writeBatchMaxDelayMs(默认 200ms),这是耐久性上的权衡。 - 插件以当前 dsh 进程的权限运行,会直接替换会话文件。安装前建议检查源码与许可证,先在测试环境用
--dry-run验证。
结尾¶
dsh-session-repacker 解决的问题很具体:DSH 逐批写入留下的万帧 zstd 日志拖慢旧会话读取。它不改数据语义,只把文件恢复成官方原生两帧形态,换来约 6 倍的打开提速和约一半的体积,同时给出了一套完整的安全防护。在 DSH「一切皆插件」的思路下,这是一个典型的存储层维护型插件。
- 目录页:https://www.skillhub.cn/plugins/kkishapppy/dsh-session-repacker
- GitHub:https://github.com/kkishapppy/dsh-session-repacker