docs: record conversation store, timeline windowing and read worker results
This commit is contained in:
@@ -724,9 +724,85 @@ Renderer 主线程降速 4 倍(Main 不降速,每次 reload 后重新应用
|
||||
175–258 ms);切换会话持平;流式场景两版方差都很大,未见一致变化。远程批量写库不在该基准
|
||||
覆盖范围内,由单元测试和 `ipc.test.ts` 验证事务次数、顺序与回放去重。
|
||||
|
||||
#### 2026-10-03 会话与消息领域(第一片)
|
||||
|
||||
- **会话 store(`conversation-store.ts`、`conversation-selectors.ts`):** 会话数组移出 App state,
|
||||
`getState()` 同步可读,取代 `conversationsRef` 及其 5 处直接写入;`set()` 先吸收流式 delta
|
||||
再同步更新。按会话 id 和列表两级通知,选择结果未变时保持同一对象。
|
||||
- **侧栏(`ConversationSidebar.tsx`):** 搜索匹配、5 秒重排、行级派生值移入侧栏自身订阅;
|
||||
切换会话时侧栏只重渲染状态翻转的两行。顺便修复 React 19.2 中 `memo` 组件内
|
||||
`useEffectEvent` 不刷新导致重排用旧列表的问题(有回归测试)。
|
||||
- **App 只订阅:** 活动会话、缓存面板的会话、数量,以及标题/审批/项目活动的按值比较
|
||||
选择器。`App.tsx` 从 11,636 行降到约 10,960 行。
|
||||
- **仍在 App:** 未读、展开、菜单、重命名、删除等界面 ID;持久化、历史加载与合并;
|
||||
活动会话的更新(含 250 ms 流式吸收)仍重渲染 App。
|
||||
|
||||
### PERF-14 长列表虚拟化
|
||||
|
||||
- **优先级 / 状态:** P2 / 待开始
|
||||
#### 2026-10-03 消息时间线窗口化
|
||||
|
||||
- **实现(`chat-message-window.ts`、`ChatHistoryPane.tsx`、`ChatTimeline.tsx`):** 自研窗口化,
|
||||
未引入依赖。只挂载视口附近的行(上限 60 行,外加获得焦点的行),其余用按实测高度或
|
||||
平均高度估算的占位块代替;行高按会话缓存(最多 24 个会话)。以视口内的一行为锚点,
|
||||
行高变化或挂载/卸载时修正滚动位置,读者看到的内容不动。
|
||||
- **保留:** 96 px 贴底阈值和流式时每帧跟随;发送消息回到底部;“加载更早”仍按 80 条扩展
|
||||
可滚动范围;笔记跳转先挂载目标再滚动;隐藏/显示和重新挂载恢复位置;隐藏面板不测量。
|
||||
分帧补全(`09c415b`/`855b941`)已删除,打开面板一次提交有界行数。
|
||||
- **滚动滞后窗口:** 视口离开已挂载范围 160 px 内才重新取窗,取窗时挂载 1.5 屏余量,避免
|
||||
每个滚动事件都重挂行。
|
||||
- **毛玻璃锚点:** 锚点以 `.chat-content` 的上内边距为基准,切换毛玻璃时阅读位置不变
|
||||
(由 `tests/frosted-glass.electron.test.ts` 在真实 Electron 中验证,该测试改为按消息 id 跟踪
|
||||
锚点行)。
|
||||
- **已知限制:** 页内查找搜不到未挂载的消息;快速甩动时可能短暂看到空白占位;单条超长
|
||||
消息仍整行挂载;估算高度会让滚动条滑块在首次经过时轻微变化。
|
||||
|
||||
### PERF-15/16 第一片:热点读路径移出 Main
|
||||
|
||||
#### 2026-10-03 只读查询 worker
|
||||
|
||||
- **实现(`readonly-query-reader.ts`、`readonly-query-worker.ts`):** 每个数据库文件一个只读
|
||||
worker 线程,沿用 `execution-stats-reader` 的模式,复用 `KnowledgeDatabase` /
|
||||
`AssistantDatabase` 的生产方法,结果与同步路径同源。最多 32 个并发请求;worker 崩溃或
|
||||
启动失败时转为同步执行,30 秒后再重启;`:memory:` 始终同步。`AbortSignal` 通过共享标志
|
||||
取消(向量扫描每 256 行检查)。没有新增 `DatabaseSync` 白名单。
|
||||
- **已移出 Main:** 知识库检索(`retrieve`、`searchHybrid`);Story Graph 读取(Agent 通过 MCP
|
||||
调用,先在 SQL 中按范围预筛,超过 5 万个对象返回 `scan_limit_exceeded`);会话搜索(一条
|
||||
SQL + 注册函数,保持 `toLocaleLowerCase().includes()` 语义)。会话列表的 N+1 查询改为两次
|
||||
批量查询,IPC 结构不变。
|
||||
- **`npm run perf:knowledge`(改用 Electron 运行):**
|
||||
|
||||
| 文本块 | 混合检索时 Main 最大事件循环延迟(同步 → worker) | 单次耗时(同步 / worker) |
|
||||
| --- | --- | --- |
|
||||
| 5,000 | 54.9 → 19.5 ms | 47.7 / 53.3 ms |
|
||||
| 20,000 | 204.3 → 19.6 ms | 188.6 / 198.9 ms |
|
||||
| 50,000 | 489.9 → 18.6 ms | 466.8 / 478.6 ms |
|
||||
|
||||
- **剩余:** 向量检索仍是全表扫描(只是不在 Main 上);写入和其余约 530 处同步调用仍在
|
||||
Main;独立数据进程和 `DatabaseSync` 白名单缩减未开始。
|
||||
|
||||
#### 2026-10-03 三项合并后的 `npm run perf:app` A/B(改动前为 `53b9ecb`)
|
||||
|
||||
不降速:新版本通过全部 60 项阈值。4× 降速(改动前 3 轮,改动后 3 轮,滚动场景另取调整后
|
||||
2 轮):
|
||||
|
||||
| 场景 | 改动前 | 改动后 |
|
||||
| --- | --- | --- |
|
||||
| 首次切换会话 p50 / p95 | 335–377 / 677–730 ms | 198–312 / 518–634 ms |
|
||||
| 切回刚看过的会话 p95 | 379–386 ms | 179–240 ms |
|
||||
| 切回最近的会话 p95 | 161–164 ms | 89–140 ms |
|
||||
| 打开 2,000 条消息会话 | 448–484 ms,帧 p95 200–225 ms | 290–354 ms,帧 p95 8–9 ms |
|
||||
| 滚动长会话:帧 p95 / 掉帧 | 17 ms / 7% | 58–67 ms / 15–16% |
|
||||
| 流式输出、流式时打字 | 两版波动都很大,未见一致变化 | 同左 |
|
||||
| 打字、空闲 | 持平 | 持平 |
|
||||
|
||||
滚动是唯一变差的场景:改动前长会话一次性挂载所有已加载行,滚动只是移动画面;窗口化后
|
||||
每隔几屏要挂载新行(含 Markdown 渲染)并测量。初版每个滚动事件都重新取窗,掉帧约 70%;
|
||||
加入滞后窗口后降到 15–16%。剩余开销主要在新行渲染和 `getBoundingClientRect` 测量,后续
|
||||
可把锚点测量合并到每帧一次,或给 Markdown 结果加缓存。
|
||||
|
||||
### PERF-14 状态
|
||||
|
||||
- **优先级 / 状态:** P2 / 进行中(消息时间线已窗口化;侧栏未虚拟化)
|
||||
- **实施条件:** `PERF-13` 完成会话与消息迁移,行组件 props 已稳定。
|
||||
- **范围:** 消息时间线和会话侧栏优先;保留滚动位置、跳转、展开状态和“加载更早消息”语义。
|
||||
替换新面板分两步渲染(`09c415b`);侧栏 5 秒重排状态随侧栏迁出 App。
|
||||
|
||||
Reference in New Issue
Block a user