zai-org / zai-org/feedback

[Bug] 多会话切换明显卡顿:实测切换连接 P90 890ms / 峰值 8.6s,伴随高频 IPC 轮询与级联加载

Open
#532 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

priority: P2
Dominant language
No language data
Stars
22
Forks
1
PR merge metrics
No merged PRs in 30d

Description

使用环境
  • 客户端:ZCode Desktop 3.11.2
  • 系统:Windows 11 x64
  • 样本:本机 2026-09-05 单日运行日志(~/.zcode/v2/logs/2026-09-05.log)与会话索引库(~/.zcode/v2/tasks-index.sqlite)统计,数据截至当日 17:49
问题描述

右侧同时管理 30+ 个会话(来自不同项目/任务)来回切换时,切换动作经常伴随明显卡顿:点开一个会话后,对话区要等几十毫秒到数秒才出内容,极端情况接近 9 秒。会话越多、单会话内容越长,越明显。

对当天日志做了统计,卡顿不是主观感受,而是结构性的:

指标 实测值
会话切换连接(v4 conversation store connect completed,n=390)P50 / P90 / P99 / Max 52.5ms / 889.6ms / 5269ms / 8577ms
超过 1 秒的切换占比 38/390 ≈ 9.7%
zcode-agent.subscribeConversationV4 单次最大 8565.3ms(全天 391 次调用)
zcode-agent.conversationPlansV4 单次最大 15255.9ms(572 次)
zcode-agent.sendConversationCommandV4 单次最大 15853.7ms(336 次)
zcode-session.readWorkspaceState 单次最大 12563.7ms(16 次)
window-controller.listTaskList 全天调用 73423 次(平均约 1.2 次/秒)
dropped buffered outbound payloads 418 条日志 / 累计丢弃 469 个 payload
stale renderer instance for sender 161 次
tasks-index.sqlite 主库 / WAL 5.13MB / 4.35MB
tasks 表 searchable_text 135 行,单条最大 153239 字符,全表合计约 251 万字符
复现步骤
  1. 侧边栏管理 30+ 个会话,其中若干为长会话(几十条消息、含工具调用与文件变更);
  2. 在这些会话之间来回切换;
  3. 观察切换后对话区出内容的等待时间;同时看日志中 v4 conversation store connect completeddurationMs 分布。
症状拆解(均可在日志中对应)
  1. 切换握手重、连接完成瞬间请求风暴:切换会话时 unsubscribe→subscribe 成对出现(当日各约 390 次),subscribeConversationV4 单次最长 8.5s;连接完成后,conversationFileChangesV4(1269 次)/ conversationRowsRangeV4(1715 次)/ conversationPlansV4(572 次)等重载请求集中倾泻,形成级联加载。
  2. listTaskList 高频轮询缺节流:全天 73423 次、平均约 1.2 次/秒,焦点切换或任务更新时 1 秒内连打多次;IPC 通道拥塞时日志出现 dropped buffered outbound payloads(418 条)与 stale renderer instance(161 次)。
  3. 会话索引库行宽:tasks 主表把聊天全文塞进单行 searchable_text(实测单条最大约 15.3 万字符),高频 listTaskList 反复把大文本读入内存页;5.1MB 主库伴随 4.35MB WAL,写放大明显。
  4. 遥测链路放大:客户端内置 @arms/rum-electron@opentelemetry/api,对上述高频 RPC 做全量 Span 包装,进一步抬高 CPU 与 GC 开销。
期望行为 / 工程建议
  1. listTaskList 增加节流/防抖与增量刷新(任务状态变化推送代替轮询,或至少合并高频请求);
  2. 切换订阅握手异步化:先渲染轻量骨架/最近视口投影,plans / fileChanges 等重载分批或按需拉取,避免连接完成瞬间的请求风暴;
  3. tasks 表 searchable_text 拆出 FTS5 虚拟表,列表查询只取标题与摘要;
  4. 遥测对高频 RPC 降采样。
关联
  • #488 / #422:同一「多会话切换」场景下的滚动定位问题。切换级联阻塞(峰值 8.6s)期间,定位/跟随逻辑可能未执行或被打断,两者或互为因果,建议一并排查。

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the 30+ session workload and inspect ~/.zcode/v2/logs/2026-09-05.log alongside tasks-index.sqlite. Trace listTaskList polling and the subscribeConversationV4 request sequence, using the reported latency, dropped-payload, and stale-renderer metrics as baselines. Because several possible causes and fixes are listed, done should include an isolated scope and before/after measurements showing faster switching without regressions.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, sqlite
Domain
databases, desktop, performance
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.