dsh-session-repacker:把 DSH 会话日志重打包为官方两帧形态,旧会话打开提速约 6 倍

前言

如果你用 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
羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

Xiaoye