前言¶
如果你用 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