extensionhost进程真泄漏内存的表现是:关掉所有编辑器标签页并等待2–3分钟,其rss内存不回落甚至持续爬升;应使用developer: open process explorer查看真实占用,而非任务管理器中混杂的“code helper”数值。

怎么看 extensionHost 进程是不是真在泄漏内存
关掉所有编辑器标签页,等 2–3 分钟,如果 extensionHost 进程 RSS 内存不回落、甚至缓慢爬升,基本就是泄漏。别信任务管理器里模糊的 “Code Helper” 数值——它混着渲染进程、GPU 进程,根本分不清谁在吃内存。
实操动作:
- 按
Ctrl+Shift+P(Win/Linux)或Cmd+Shift+P(macOS),执行Developer: Open Process Explorer - 展开
extensionHost节点,按Memory列排序 - 重点关注“空闲驻留值”:比如
esbenp.prettier-vscode关掉所有文件后还稳在 420MB,就是高危信号 - 同时看
CPU列是否有周期性尖峰,常对应未节流的定时器或未取消的fetch轮询
怎么用 Chrome DevTools 抓插件的真实泄漏对象
VSCode 自带的调试器不支持堆快照对比,必须走 chrome://inspect。插件跑在 Extension Host(Node.js/V8)里,泄漏对象类型和浏览器不同:Detached 不是 DOM 专属,Closure 和 EventEmitter 才是主力。
关键步骤:
- 终端启动插件开发主机时加
--inspect-extensions(如code --extensionDevelopmentPath=.后手动附加) - Chrome 访问
chrome://inspect→Configure→ 添加localhost:9229→ 刷新后点inspect - 拍三次快照:
snapshot-0(空载)、snapshot-1(打开一个 .drawio 或触发 GitLens 历史加载)、snapshot-2(关闭文件 + 等 30 秒 GC 后) - 右键
snapshot-2→Compare to previous snapshot,按Retained Size降序,筛Closure、Detached、Timeout类型
为什么禁用插件后内存根本不降
禁用只是标记“下次不加载”,旧 extensionHost 进程仍驻留,所有句柄、缓存、监听器全在。你看到的“高内存”是上一个会话的残留,不是当前配置的问题。
必须做的动作:
- 禁用可疑插件(如
gitlens、ms-python.python)后,**关闭当前 VSCode 窗口再重新打开** - 或者执行
Developer: Reload Window,观察内存是否大幅回落——若回落,说明泄漏在会话上下文;若纹丝不动,就得查进程级卸载逻辑 - 检查插件
deactivate()函数里有没有真正调用disposables.forEach(d => d.dispose()),尤其注意Webview.onDidReceiveMessage是否配对off(),workspace.onDidChangeTextDocument是否有dispose()清理
自己写插件时最容易漏掉的三处防护
很多泄漏不是逻辑错,是忘了加几行“保命代码”。V8 不会替你清理闭包、不会帮你清 Map、也不会自动释放 Webview 实例。
底线操作:
- 避免在
activate()里require大型依赖(如acorn),改用import()动态加载,且只在需要时触发 - 缓存必须带 TTL 或 LRU,例如用
lru-cache替代Map,并设maxSize: 100,否则大项目下元数据无限累积 - 调试阶段加一行
console.log(`[MEM] ${process.memoryUsage().heapUsed / 1024 / 1024} MB`)打点,观察每次打开/关闭文件后的增量——突增 >5MB 就该查Retainers链
onDidSaveTextDocument,一个没节流,一个没防抖,结果保存瞬间触发两次全量 AST 解析,主线程直接卡死。这种问题单看任一插件都“正常”,只有在 Process Explorer 里看到 CPU 和内存同步尖峰,才暴露真相。











