Files
DevFlow/docs/05-代码审查/aichat效率走查-2026-08-09.md

10 KiB
Raw Permalink Blame History

aichat 运行效率走查报告(多角度)

走查日期:2026-08-09 范围:aichat 前后端全链路(后端 agentic 2910 行 + audit + tools + 流式;前端 composables/ai + MessageList/ChatInput/TopBar 方法:6 路并行 Explore agent(单轮成本/工具执行/流式渲染/前端交互/会话生命周期/LLM成本) 性质:只走查登记,不实施代码 触发:用户反馈「aichat 运行的效率很低」+「成本走查,比如有的 LLM 要求的缓存命中率规则」


一、单轮执行成本(13 项)

P1

  • R1-1 每轮全量历史重放,无增量context/mod.rs:184-253 + agentic:1492-1527)——第 k 轮 prompt≈Σ历史,R 轮总 input≈O(R²);追加尾部的每轮新 tool_result 是必然 cache miss
  • R1-2 上一轮已见工具结果本轮仍全量重放summarize_tool_results view-only:1540-1551)——grep/search 的 matches:[] 每轮重复
  • R1-3 自动压缩阈值过惰性context_lifecycle.rs:88-95>61K token 才触发)——普通会话永不压缩,全量重放无兜底

P2

  • R2-1 每轮 ≥4 次全历史深克隆build_for_request + save + count_recent_failures + check_stall_breaker2 次持 session 锁)
  • R2-2 每轮必 save_conversation(全量 clone + truncate_for_persist + 序列化 + DB 元数据重写)
  • R2-3 estimated_prompt 每轮全量重估 token(与 history_tokens 增量维护重复)

P3

R3-1 重试/候选切换全量 to_vec clone · R3-2 summarize 对未变化历史每轮重算 · R3-3 system_prompt 每轮整体克隆(未打 cache_control 断点)· R3-4 build_system_prompt 每次 loop/resume 查库(list_active×2)· R3-5 每轮重建 provider + keyring 解析 · R3-6 process_tool_calls 每工具全量扫历史 · R3-7 无 token 预算型终止(空转到 10 轮)


二、工具执行开销(9 项)

P1

  • T1-1 审计每工具 ≥1 次串行 INSERTaudit/mod.rs:684-721,全经单全局 DB 锁,无批量)——单轮 N 工具 = N 次 INSERTjoin_all 后的串行尾巴
  • T1-2 只读缓存是"假缓存"cache.rs:251-330)——每工具全量扫历史 + 1 次 DB SELECT,非 O(1) 索引;miss 代价>收益
  • T1-3 git 工具不进只读缓存git.rs:99-133,每轮跑子进程;module.rs 5s git 缓存不共享)——LLM 失忆重调 git 完全没被治
  • T1-4 每轮对完整历史重处理build_for_request + summarize + estimated_prompt + 2 次全量 clone

P2

  • T2-1 审批/授权每 Med/High 工具最多 3 次 DB 往返 + 全量历史扫auto_exec_mode 等低频配置每轮查库)
  • T2-2 read_file/read_symbol 每次全量读文件(≤1MB)(分段读也全读,offset 不同缓存 miss
  • T2-3 缓存命中把全量内容直接 push messages(不 namespace+ 审计落全量 → 缓存反放大历史
  • T2-4 entity_resolve 每工具 clone args + 每工具一次 list_active 全表查询

P3

T3-1 工具事件双写 + 每工具一个心跳 task


三、流式渲染效率(12 项)

P1

  • S1-1 每帧全量 lexer + 单块回复整段重 parse,块级 memo 退化useStreamRenderer.ts:77-97/130-154)——无 \n\n 的长文回复每帧全文 lexer+parse+sanitize,整轮 O(n²),长文卡顿主因
  • S1-2 长尾代码块/末块每帧重跑 hljs 高亮:146-149 + useMarkdown:87-111

P2

  • S2-1 每次 flush 两次整组件重渲染currentText 触发 + streamingBlocks rAF 触发,:219-236~40 次/s 整树求值
  • S2-2 renderMd 缓存命中前先跑 wrapNakedDiff 全文扫描useMarkdown.ts:191-197
  • S2-3 isToolResultJson 对每条 JSON 形消息每帧 JSON.parseMessageList:698-708
  • S2-4 handleEvent 每活跃事件重复 setConvState('generating')useAiEvents.ts:122-124,同值无短路)
  • S2-5 AiCommandOutputrun_command 逐行)未合批,事件风暴command_stream.rs:39-48,几百上千行命令→每秒上百 IPC)
  • S2-6 已完成块每帧重算 simpleHash + 新子串做 Map key 哈希

P3

S3-1 每 delta 文本空闲计时器/看门狗重建 · S3-2 切会话缓冲双清 no-op · S3-3 tail-${tailSeq} 恒等于 tail-1(注释误导)· S3-4 messages deep watch 每工具翻转 JSON.stringify 全量

已核查无问题(Info

后端 50ms 合批真生效(stream_recv.rs:346-352)· rAF 节流真生效 · 消息侧无 O(n²)(isLastAi O(1))· 内存缓存界内(_blockCache≤300/_mdCache≤200/currentText 完成即清)


四、前端交互效率(12 项)

P1

  • F1-1 回合收尾双拉会话列表useAiLifecycleEvents.ts:119 + notify→listener 再拉,每回合 2 次全量 list IPC)
  • F1-2 notifyConversationChanged 同窗口自触发冗余重拉aiShared.ts:21 emit 回传同窗口 listener;删除活跃会话可达 5 IPC)
  • F1-3 loadConversations 无防抖(8+ 处调用,整体替换数组→侧栏全量重渲染)

P2

  • F2-1 switch 无条件多 1 次 pendingToolCalls IPC(纯文本会话也白拉)
  • F2-2 switch 主线程同步全量 parseJSON.parse + parseConvMessages 每条 toolCall 再 parse
  • F2-3 MessageList deep watch 每次 messages 变更全量 JSON.stringify 快照
  • F2-4 输入联想每键全量过滤 + 首次 @ 全量拉 tasks
  • F2-5 TopBar 多个 computed 每次 messages 变更全量扫描historyMsgs/summaryMsgs/contextInfo

P3

F3-1 滚动边沿 buildActiveToolIds 全量遍历 · F3-2 每 delta 定时器重建(看门狗+文本空闲)· F3-3 AiChat 启动串行 IPC 链(约 5 次)· F3-4 persistUiState 每次写整包 df-ai-ui


五、会话生命周期(16 项)

P0

  • L0-1 save_conversation 每轮 O(N) 全量克隆+截断+记录构建,CPU 在主线程conversation.rs:254-343,单线程 runtime)——"无变化捷径"在 records 构建后才判定,每轮白付全部 CPU;N 轮工具对话 ≈N+1~N+2 次 save
  • L0-2 system prompt 每次用户操作全量重建 + 串行 6-8 次 DB 查询chat.rs:527-651 + prompt.rs:280-343)——全部落在「点击→首 token」关键路径,project/task 清单可缓存
  • L0-3 自动压缩在 loop 内同步阻塞整轮context_lifecycle.rs:159-167,非流式 LLM 最长 60s+ 压缩后必全量 DELETE+INSERT 重写

P1

  • L1-1 最终轮重复 saveagentic:1918 + :2111 收敛时再 spawn
  • L1-2 每轮 build_for_request + sanitize + pairing + estimated_prompt 共 5-6 次全量遍历
  • L1-3 会话切换全量读库 + 全量重估 token + 全量重跑意图识别restore 时对每条 re-estimate + re-recognize
  • L1-4 每次生成结束在所有窗口触发会话列表全量刷新 + 事件双写55 处 emit + publish_event 双写)
  • L1-5 知识注入每次发送全量克隆消息 + 两次 DB 检索keyword + vector,关键路径)

P2

L2-1 Checkpoint 每 20 条消息全量序列化 · L2-2 单次 save 对 session 锁加锁 3 次 · L2-3 active provider 在 send→loop 各查一次库 · L2-4 estimated_prompt 每轮全量重算 · L2-5 空标题会话切换触发额外 LLM 标题生成 · L2-6 心跳每 20s 无条件广播

P3

L3-1 所有重生成路径同样重建 system promptregenerate/edit/force_send)· L3-2 事件总线双写在热点仍存在(app.emit 全窗口广播)

关键前提

Tauri Windows 单线程 tokio runtime——所有 CPU 密集操作主线程串行,任一长任务阻塞全部 IPC。最高优先级:L0-1 save 提前判定 + L0-2 缓存 + L0-3 压缩后台化。


六、LLM 成本 / 缓存命中率(12 项)

核心结论DevFlow 从未向任何 provider 发送 cache_control/cache_breakpoint,且 system prompt 每轮用实时 DB 数据重建 → 前缀缓存既没开、前缀也不稳定,多轮对话几乎 100% 缓存不命中,每轮全价支付全量历史 + 全量 system。代码只做了「读回 cache_read/cache_creation 计费展示」,从未「请求缓存」。

P0

  • C0-1 全链路无 cache_control 注解,Anthropic 提示缓存根本没启用anthropic_helpers.rs:22-36 无字段;system 是纯 String 无法表达 breakpoint,需改 text-block 数组)
  • C0-2 system prompt 每轮用实时 DB 数据重建,前缀字节不稳定 → 跨轮缓存全废prompt.rs:295/315 list_active 20+20 注入,agent 改数据即变;建议挪到消息流只留静态指令)

P1

  • C1-1 日期在 system prompt 位置 0,跨天失效整条前缀prompt.rs:45 当前日期)
  • C1-2 每轮全量重发全部历史,成本 O(n²),无缓存兜底(10 轮实测单次请求可达 ~12 万 token 全价)
  • C1-3 augmentation/知识注入拼进 system,随轮变化再添失效源chat.rs:639-652

P2

  • C2-1 模型路由从不因简单意图降档,贵模型低用router.rs weight 主键,tier 仅 tiebreakChat 意图也应降档)
  • C2-2 重试发送字节完全相同请求,无缓存 → 每次重试重复全价
  • C2-3 system prompt 本身膨胀(文档探索段 140-180 行常驻)+ 重复注入技能/工作流/目标
  • C2-4 标题生成/规划/压缩是独立 LLM 调用,不共享前缀缓存

P3

C3-1 tools 每轮全量序列化无 cache_control 与 system 一起缓存 · C3-2 AnthropicRequest.system 纯 String 需结构改造 · C3-3 采样参数合理(确认项)

修复优先级(成本 agent 建议)

  1. C0-1 + C0-2 一起修(加 cache_control + 稳定 system 前缀)才能产生真实命中率
  2. C1-1/C1-2/C1-3(日期与易变段挪出稳定前缀、augmentation 改注入消息流)→ 多轮 loop 输入成本砍 1/51/10
  3. C2-1 模型降档(收益独立于缓存,可并行)

七、优先级建议(合并 6 路)

成本大头(后端)R1-1 全量历史重放 + R2-1 每轮 4 次深克隆 → 增量/窗口化 卡顿主因(渲染):S1-1 单块回复每帧全量渲染 → 增量 lex/parse 无谓开销(前端):F1-1/2/3 列表刷新收敛(合并一个 debounced scheduleConversationsRefresh DB 瓶颈T1-1 审计批量事务 + T1-2 只读缓存 O(1) 索引 成本(LLM 缓存)C0-1 + C0-2cache_control + 稳定前缀)→ 命中率从 ~0% 提升到可复用


八、登记去向

  • 本报告:docs/05-代码审查/aichat效率走查-2026-08-09.md
  • 看板:docs/todo.md 增登记条目
  • memory 指针:待补齐