Skip to content

Long wait when init Roo Code #3919

@zhangtony239

Description

@zhangtony239

App Version

v3.18.2

API Provider

Not Applicable / Other

Model Used

N/A

🔁 Steps to Reproduce

  1. Start VSCode
  2. Wait, and you will feel this.

💥 Outcome Summary

Expected Roo Code would be loaded in a few seconds, but almost 1min is used.

📄 Relevant Logs or Errors (Optional)

经过详细的日志分析,VSCode 插件启动缓慢的主要原因已确定,并可以提出相应的优化建议。

**分析结果总结:**

插件的整体激活过程 (`activate` 函数) 大约耗时 **2.285 秒**。主要的性能瓶颈按影响程度排序如下:

1.  **大量密钥的同步读取 (约 1.2 秒)***`ContextProxy.initialize` ([`src/core/config/ContextProxy.ts:53`](src/core/config/ContextProxy.ts:53)) 过程中,插件通过 `vscode.ExtensionContext.secrets.get()` ([`src/core/config/ContextProxy.ts:65`](src/core/config/ContextProxy.ts:65)) 接口读取了十几个密钥(如 `apiKey`, `glamaApiKey`, `openRouterApiKey` 等)。
    *   **每次 `secrets.get()` 调用都非常耗时,平均在 1.1 秒以上**。由于这些调用在 `Promise.all` ([`src/core/config/ContextProxy.ts:71`](src/core/config/ContextProxy.ts:71)) 中是并发的,所以总耗时取决于最慢的一次调用,但多次调用本身就表明这是一个重度依赖系统密钥链的操作。这是启动性能的最大瓶颈。

2.  **设置文件迁移 (约 1.05 秒)**
    *   `migrateSettings` ([`src/utils/migrateSettings.ts:15`](src/utils/migrateSettings.ts:15)) 函数在需要进行文件重命名时,消耗了约 1 秒。这主要是一次性成本,在设置迁移完成后不会重复发生。

3.  **首次加载自定义模式文件 (约 837 毫秒)**
    *`CustomModesManager.getCustomModes` ([`src/core/config/CustomModesManager.ts:191`](src/core/config/CustomModesManager.ts:191)) 首次执行(缓存未命中)时,读取和解析全局及项目级的自定义模式文件(`.yml``.roomodes`)耗时较长。

4.  **Webview HTML 内容加载 (约 521 毫秒)**
    *`ClineProvider.resolveWebviewView` ([`src/core/webview/ClineProvider.ts:320`](src/core/webview/ClineProvider.ts:320)) 中,通过 `getHtmlContent` ([`src/core/webview/ClineProvider.ts:643`](src/core/webview/ClineProvider.ts:643)) 或 `getHMRHtmlContent` ([`src/core/webview/ClineProvider.ts:534`](src/core/webview/ClineProvider.ts:534)) 为 Webview 生成和设置 HTML 内容消耗了约半秒。

5.  **`McpHub` 初始化**
    *   在本次日志收集中,`McpHub` ([`src/services/mcp/McpHub.ts:1`](src/services/mcp/McpHub.ts:1)) 的构造非常快 (约 3 毫秒)。这表明可能没有配置活动的、需要启动子进程或进行耗时网络连接的 MCP 服务器。**然而,如果用户在实际使用中配置了此类服务器,`McpHub` 的初始化(特别是 `connectToServer` ([`src/services/mcp/McpHub.ts:425`](src/services/mcp/McpHub.ts:425)) 中的子进程启动和网络连接)极有可能成为另一个主要的性能瓶颈。**

**根本原因:**
插件的 `activationEvents` ([`src/package.json:48`](src/package.json:48)) 设置为 `["onLanguage", "onStartupFinished"]`。特别是 `onStartupFinished` ([`src/package.json:50`](src/package.json:50)),它导致插件在 VSCode 启动完成后立即执行上述所有耗时操作,从而严重影响了用户感知的编辑器启动速度和响应性。

**优化建议:**

1.  **优化激活事件 (`activationEvents`)**
    *   **首要且最重要的改动**:移除或替换 `onStartupFinished` ([`src/package.json:50`](src/package.json:50))。考虑更具体的激活事件,例如:
        *   `onCommand:{commandId}`: 当用户执行特定命令时激活。
        *   `onView:{viewId}`: 当用户打开插件的自定义视图(如侧边栏)时激活 (例如 `onView:roo-cline.SidebarProvider`)。
        *   `workspaceContains:{globPattern}`: 当工作区包含特定文件或文件夹时激活。
    *   目标是实现**延迟加载 (Lazy Loading)**,仅在用户确实需要使用插件功能时才执行激活逻辑。

2.  **优化密钥读取 (`ContextProxy.initialize`)**
    *   **按需读取密钥**:不要在插件激活时一次性读取所有可能的密钥。仅在实际需要使用某个服务的 API 密钥时才去调用 `secrets.get()`
    *   **缓存已读取的密钥**`ContextProxy` 似乎已经有了 `secretCache` ([`src/core/config/ContextProxy.ts:39`](src/core/config/ContextProxy.ts:39)),确保其有效利用,避免重复读取。
    *   **提示用户输入**:如果某个功能依赖的密钥不存在,可以考虑在用户首次使用该功能时提示用户输入,而不是在启动时静默失败或尝试读取一个不存在的密钥。

3.  **异步化和推迟非核心初始化**
    *   **设置迁移 (`migrateSettings`)**: 虽然是一次性的,但如果可能,可以考虑将其推迟到插件激活后的某个空闲时刻执行,或者在用户首次与插件交互时执行,并显示一个简短的提示。
    *   **自定义模式加载 (`CustomModesManager.getCustomModes`)**:
        *   首次加载自定义模式可以在后台异步进行,不阻塞主激活流程。
        *   在模式数据准备好之前,可以显示一个加载状态或使用默认模式。
    *   **Webview 内容加载 (`getHtmlContent`)**: Webview 的 HTML 内容可以在视图实际可见时 (`resolveWebviewView` 被调用时) 再加载,这已经是当前做法,但其内部的 `getState` 调用可以进一步优化,避免不必要的阻塞。

4.  **优化 `McpHub` 初始化 (如果配置了耗时服务器)**
    *   如果用户配置了 MCP 服务器,它们的连接和初始化 (`connectToServer` ([`src/services/mcp/McpHub.ts:425`](src/services/mcp/McpHub.ts:425))) 应该在后台异步进行,不阻塞主激活流程。
    *   可以先显示服务器列表为“连接中”状态,连接成功或失败后再更新UI。

5.  **代码拆分和动态导入**
    *   对于大型模块或不常用的功能,考虑使用动态 `import()` 来按需加载代码,减少初始包体积和解析时间。

6.  **移除或替换不必要的同步操作**
    *   仔细审查激活路径上的所有代码,将不必要的同步文件I/O、大量计算等替换为异步操作,或将其移出关键路径。

**实施优先级:**
建议首先解决**激活事件****密钥读取**这两个问题,因为它们对启动性能的改善最为显著。然后逐步处理其他优化点。

在进行这些优化后,建议再次使用我们添加的性能日志来衡量改进效果。

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions