Files
qiming/qimingclaw/crates/agent-electron-client/docs/optimization/FIRST-MESSAGE-PERF-OPT-2026-03-23.md

7.3 KiB
Raw Blame History

首消息性能优化报告

日期: 2026-03-23 优化目标: 降低首消息冷启动Agent 响应延迟 优化前: ~1662ms 优化后: ~349ms 提升幅度: 79%


1. 问题分析

1.1 原始性能数据

首消息 ensureEngineForRequest 耗时分解:

ensureEngine 总耗时: 1662ms
├── parseCtxServers: 5ms
├── syncMcp: 1315ms ← 主要瓶颈79%
└── getOrCreate: 342ms
    ├── memory: 231ms
    └── init: 102ms

1.2 瓶颈定位

阶段 耗时 占比 说明
syncMcpConfigToProxyAndReload 1315ms 79% MCP 代理同步,首消息必须等待
ensureMemoryReadyForSession 231ms 14% Memory 服务初始化
engine.init 102ms 6% ACP 引擎进程启动
其他 14ms 1% 配置解析、MCP 提取等

2. 优化方案

2.1 优化一MCP Proxy Bridge 预热

原理: 在服务 init() 时后台预热 MCP proxy bridge避免首消息同步阻塞。

代码位置: src/main/services/engines/unifiedAgent.ts

/**
 * 🚀 性能优化:后台预热 MCP proxy bridge
 * 在 init() 时调用,避免首包 syncMcp 阻塞 ~1.3s
 */
private warmupMcpBridge(): void {
  (async () => {
    try {
      const { syncMcpConfigToProxyAndReload } = await import("../packages/mcp");
      // 使用空配置预热(仅启动默认服务如 chrome-devtools
      await syncMcpConfigToProxyAndReload({});
      log.info("[UnifiedAgent] ✅ MCP proxy bridge 预热完成");
    } catch (err) {
      log.warn("[UnifiedAgent] MCP proxy bridge 预热失败:", err);
    }
  })().catch(() => {});
}

调用时机: 在 init() 方法末尾调用与其他预热任务Engine 预热、Memory 预热)并行执行。

2.2 优化二syncMcp 与 ensureMemoryReady 并行执行

原理: 当 MCP 配置变更且需要创建新引擎时,将 syncMcpensureMemoryReady 并行执行。

代码位置: src/main/services/engines/unifiedAgent.tsensureEngineForRequest()

// 🚀 性能优化:只有在 MCP 配置变更时才调用 syncMcpConfigToProxyAndReload
// 同时,如果需要创建新引擎(无现有引擎),并行执行 ensureMemoryReady
const needCreateEngine = !existingEngine || !existingEngine.isReady;
let memoryReadyPromise: Promise<void> | null = null;

if (mcpChanged) {
  const syncStart = Date.now();
  try {
    const { syncMcpConfigToProxyAndReload } = await import("../packages/mcp");
    const syncPromise = syncMcpConfigToProxyAndReload(requestMcpServersEarly);

    // 🚀 性能优化:如果需要创建新引擎,并行执行 ensureMemoryReady
    if (needCreateEngine && memoryService.isInitialized()) {
      memoryReadyPromise = memoryService.ensureMemoryReadyForSession()
        .then(() => {
          log.debug(`⏱️ [PERF] ensureMemoryReady 并行完成: ${Date.now() - syncStart}ms`);
        })
        .catch((err) => {
          log.warn("[UnifiedAgent] Memory sync check failed:", err);
        });
    }

    await syncPromise;
  } catch (e) {
    log.warn("[UnifiedAgent] 动态同步 MCP 配置到 proxy 失败:", e);
  }
}

getOrCreateEngine 方法修改:

async getOrCreateEngine(
  projectId: string,
  effectiveConfig: AgentConfig,
  memoryReadyPromise?: Promise<void> | null,  // 新增参数
): Promise<AcpEngine> {
  // ...

  // 🚀 性能优化:如果已有并行的 memoryReadyPromise直接等待它
  if (memoryReadyPromise) {
    await memoryReadyPromise;
  } else if (memoryService.isInitialized()) {
    await memoryService.ensureMemoryReadyForSession();
  }

  // ...
}

2.3 已有优化(复用)

以下优化在之前已实现,本次优化复用:

  1. 快速路径 1: 无配置变更 → 直接返回现有引擎7ms
  2. 快速路径 2: MCP 未变更 → 跳过 syncMcp
  3. Engine 预热池: 预热 claude-code 和 qimingcode 引擎
  4. Memory 预热: init() 时后台执行 ensureMemoryReadyForSession()

3. 测试对照

3.1 测试环境

  • 应用版本: 0.9.1
  • 测试时间: 2026-03-23 17:53
  • 测试场景: 重启应用后发送首条消息

3.2 优化前日志2026-03-20

ensureEngine 总耗时: 1662ms
├── parseCtxServers: 5ms
├── syncMcp: 1315ms
└── getOrCreate: 342ms
    ├── memory: 231ms
    └── init: 102ms

3.3 优化后日志2026-03-23

[17:52:55] [info] 🔥 后台预热 Engine: claude-code
[17:52:55] [info] 🔥 后台预热 Engine: qimingcode
[17:52:55] [info] ✅ 预热 Engine 就绪,等待复用: claude-code
[17:52:56] [info] ✅ MCP proxy bridge 预热完成
[17:52:58] [info] ✅ 预热 Engine 就绪,等待复用: qimingcode

[17:53:34] 首消息请求到达
[17:53:34] [debug] ⏱️ [ensureEngine][PERF] 解析 context_servers 耗时: 6ms
[17:53:34] [info]  ⏱️ [PERF] 走完整路径: 无现有引擎, MCP变更(新7个)
[17:53:34] [debug] ⏱️ [PERF] ensureMemoryReady 并行完成: 2ms
[17:53:34] [info]  ⏱️ [PERF] syncMcp 完成: 耗时 2ms | 并行memory=true
[17:53:34] [debug] ⏱️ [ensureEngine][PERF] 提取 real MCP servers 耗时: 0ms
[17:53:34] [debug] ⏱️ [ensureEngine][PERF] ensureBridgeStarted(有MCP) 耗时: 0ms
[17:53:34] [debug] ⏱️ [getOrCreateEngine][PERF] 等待并行 ensureMemoryReady 完成: 231ms
[17:53:34] [debug] ⏱️ [getOrCreateEngine][PERF] engine.init 耗时: 105ms
[17:53:34] [info]  ⏱️ [getOrCreateEngine][PERF] 总耗时: 336ms | 使用并行memory=true
[17:53:34] [info]  ⏱️ [ensureEngine][PERF] 总耗时: 349ms | 并行优化=true
[17:53:34] [info]  ⏱️ [HTTP][PERF] /computer/chat 总耗时: 362ms

3.4 性能对比表

指标 优化前 优化后 提升幅度
syncMcp 1315ms 2ms 99.8%
ensureEngine 总耗时 1662ms 349ms 79%
/computer/chat 总耗时 ~1700ms 362ms 79%

3.5 优化后耗时分解

ensureEngine 总耗时: 349ms
├── parseCtxServers: 6ms
├── syncMcp: 2ms ← 预热后从 1315ms 降至 2ms
├── extractReal: 0ms
├── ensureBridge: 0ms
└── getOrCreate: 341ms
    ├── memory: 231ms ← 与 syncMcp 并行执行
    └── init: 105ms

4. 优化效果总结

4.1 关键收益

  1. MCP Proxy Bridge 预热: 消除首消息 ~1.3s 阻塞
  2. 并行执行: Memory 准备与 MCP 同步重叠执行
  3. Engine 预热池: 复用已启动的引擎进程

4.2 用户体验改善

场景 优化前 优化后
首消息响应 ~1.7s ~0.35s
用户感知 明显延迟 接近即时

4.3 注意事项

  1. 预热时机: 所有预热任务在 init() 末尾启动,不阻塞应用启动
  2. 内存占用: 预热引擎会占用额外内存,但通过预热池容量限制(当前 1 个/类型)控制
  3. 配置变更: 如果首消息的 MCP 配置与预热配置差异较大,仍需同步,但比冷启动快

5. 相关文件

  • src/main/services/engines/unifiedAgent.ts - 主优化文件
  • src/main/services/packages/mcp.ts - MCP proxy 管理
  • src/main/services/packages/mcpHelpers.ts - MCP 配置比较工具

6. 参考资料