TauriTavern/docs/CurrentState/BootstrapOptimization.md

64 lines
3.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Bootstrap Optimization(现状)
本文记录 **已经落地** 的 bootstrap / 启动阶段优化中,与“冷启动内存基线”强相关的部分实现快照。
> 完整的分阶段启动(Shell/Core/Full/APP_READY)链路请看:`docs/CurrentState/StartupOptimization.md`。
## TokenCache(Chat Completions)避免 cold-start whole-load
### 解决的问题
历史实现会在 `initTokenizers()` 中把 IndexedDB 里的 `tokenCache`(整库大对象)一次性读入 JS 内存,导致移动端冷启动常驻集膨胀。
### 当前实现(契约)
- **存储分区**:不再使用整库 key `tokenCache`,改为按 chat 分区持久化 `tokenCache:${chatId}`。
- **启动不加载**:`loadTokenCache()` 只做 legacy key 清理(删除 `tokenCache`),不再读取整库对象。
- **只常驻当前桶**:内存只持有“当前 chat 的一个桶”(`tokenCacheState`),切换 chat 会重置到新桶并按需懒加载。
- **事件语义一致**:
- `CHAT_CHANGED`:预热当前 chat 桶(懒加载触发点)
- `CHAT_DELETED` / `GROUP_CHAT_DELETED`:删除对应 `tokenCache:${chatId}`,避免磁盘堆积
- **写回策略**:`saveTokenCache()` 仅 flush 当前 chat 桶(dirty 才写回),不再整库写回。
### 兼容性边界
- cache 是性能优化,不影响 token 计数正确性;升级后旧整库缓存会被清理,短期缓存会重新变冷(可接受的 tradeoff)。
### 关键代码位置
- `src/scripts/tokenizers.js`:`loadTokenCache()` / `saveTokenCache()` / `resetTokenCache()` / `tokenCacheState` / `initTokenizers()` 事件挂载
---
## ItemizedPrompts(Prompt Inspector)避免 chat-open whole-load
### 解决的问题
历史实现会在打开聊天时执行 `loadItemizedPrompts(getCurrentChatId())`,并从 IndexedDB 一次性加载 `chatId -> itemizedPrompts[]` 整包数组。
该数组的单条 record 内含大量长字符串(`rawPrompt/finalPrompt/worldInfo/...`),体积通常远大于聊天正文,导致移动端 WebView renderer 常驻集显著膨胀。
### 当前实现(契约)
- **存储形态(Index + Record)**:
- Index:`tt_prompts_index:${chatId}` → `Array<{ mesId, recordId }>`
- Record:`tt_prompts_record:${chatId}:${recordId}` → 单条 prompt artifacts(原 record 全量)
- **打开聊天只加载 Index**:`loadItemizedPrompts(chatId)` 仅恢复 `mesId -> recordId` 映射,不加载任何 record。
- **点击才加载 Record**:`.mes_prompt` 点击后,`promptItemize()` 按 `mesId` 懒加载对应 record(以及可选的上一条 record 用于 diff)并渲染 Inspector。
- **生成链路不再常驻 records**:生成结束写入 record + 更新 index,不再把 record `push` 到全局数组里常驻。
- **消息编辑语义保持**:
- `swapItemizedPrompts()`:仅交换 index 的 `mesId` 映射
- `deleteItemizedPromptForMessage()`:按上游语义 shift 后续 `mesId`,并删除被删除消息的 record
- **删除/清理覆盖完整**:
- chat 删除会清理 Index + Records(不留磁盘残留)
- `clearPrompts` 会清空整个实例
### 兼容性边界
- 仍复用 `localforage` 实例名 `SillyTavern_Prompts`,保证与上游/生态对存储实例名的假设一致。
- legacy 格式(`chatId -> array`)在首次进入该 chat 且 index 不存在时,会被迁移为 Index + Records 并删除旧 key(一次性成本,后续打开聊天不再 whole-load)。
### 关键代码位置
- `src/scripts/itemized-prompts.js`:Index/Record keys、加载/迁移、Inspector 懒加载、swap/delete 语义
- `src/script.js`:生成写入、按钮显示(index presence)