先建立基线与判断归因
排查的前提是把「感觉卡」变成可观测数据。打开命令面板执行 Developer: Show Running Extensions,会列出每个扩展的激活时间与耗时;Developer: Toggle Performance 显示键入延迟、渲染时间;Developer: Show Running Extensions 之外还有内置的扩展宿主进程监控,能看到 CPU 与内存占用。
区分渲染层与扩展层很关键:如果键入延迟高但 CPU 不在 Code Helper (Plugin) 上,多半是渲染器或语言服务(如 TS server)问题;如果某个扩展宿主长期占用高 CPU,几乎可以确定是它。任务管理器里 Code Helper (Renderer)、Code Helper (Plugin)、Code Helper (Watcher) 三个角色的分工要记住:Watcher 专职处理文件监视。
另一个必备动作是用 code --status 输出当前会话的进程与内存快照,以及用空窗口复现:code --disable-extensions . 打开项目。如果禁用全部扩展后依然卡,问题在编辑器配置、文件数量或工作区本身,而不在扩展。
# 空窗口打开,禁用全部扩展——最直接的归因手段
code --disable-extensions .
# 只跑单个扩展,用于二分定位
code --disable-extensions --locate-extension ms-python.python
# 查看当前会话进程与内存快照
code --status
# 界面内操作
# 命令面板 -> Developer: Show Running Extensions
# 命令面板 -> Developer: Toggle Performance
# 命令面板 -> Developer: Open Extension Host Logs扩展二分定位
扩展数量少(20 个以内)时,逐个禁用最直接。数量多时用二分法:把所有扩展移到临时目录,然后每次放回一半,重复直到定位到单个扩展。二分的价值在于把 N 次测试降到 log2(N) 次,40 个扩展只需 6 轮。
比二分更实用的日常做法是「用三个命令看嫌疑」:Developer: Show Running Extensions 里按启动时间排序,最慢的几个优先怀疑;然后对该扩展执行 Developer: Restart Extension Host 看卡顿是否消失;再看 Developer: Open Extension Host Logs 有没有反复报错或循环。
定位后有三种处置:升级(很多性能问题在扩展新版本已修)、降级锁定版本(团队统一锁住,避免每人不同)、或用 extensions.json 里的 "unwantedExtensions" 建议禁用。要注意 VS Code 的扩展建议机制不等于强制,用户仍可安装。
// .vscode/extensions.json —— 团队统一扩展集合与禁用建议
{
"recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
"unwantedExtensions": [
{
"identifier": {
"id": "some.heavy-extension"
},
"recommendation": "该扩展在大型仓库中显著拖慢启动,请在团队内统一禁用"
}
]
}
// 二分定位脚本骨架(Bash)
// 1) 备份当前扩展目录
// 2) 循环:恢复一半扩展 -> code --disable-extensions . 复现 -> 记录卡顿程度files.exclude 与 search.exclude:控制索引与搜索范围
这两个设置常被混淆,职责不同:files.exclude 决定哪些文件不出现在文件树与资源管理器的搜索中;search.exclude 决定哪些文件在执行搜索时被跳过。用 glob 模式(而不是路径模式)可以更精确地按文件名或扩展名过滤。
真正影响性能的是默认配置里那些被隐式排除的目录:.git、node_modules、dist、build、.next、target、vendor。VS Code 默认排除了一些,但一旦你在工作区里做 Add Folder to Workspace 或引入 monorepo 结构,默认值往往不够,需要显式补充。
合理的配置原则是:把生成物目录排除出文件树(减少文件监视与资源管理器渲染压力),把超大二进制目录排除出搜索(避免搜索时一次性读取海量内容)。同时配合 search.useIgnoreFiles: true 与 search.useGlobalIgnoreFiles: true 让 .gitignore 与 .ignore 生效,通常这一项就能解决大部分搜索卡顿。
// settings.json
{
"files.exclude": {
"**/.git": true,
"**/node_modules": true,
"**/dist": true,
"**/build": true,
"**/.next": true,
"**/target": true,
"**/.venv": true,
"**/*.log": true
},
"search.exclude": {
"**/node_modules": true,
"**/dist": true,
"**/build": true,
"**/target": true,
"**/*.min.js": true,
"**/*.map": true,
"**/pnpm-lock.yaml": true
},
"search.useIgnoreFiles": true,
"search.useGlobalIgnoreFiles": true,
"search.smartCase": true
}大仓库的索引与文件监视调优
在超过几十万文件的仓库里,文件监视(watcher)会吃满 inode 和 CPU。Linux 上最有效的三招是:把 files.watcherExclude 指向生成物目录、启用原生递归监视(files.watcherUsePolling: false,多数场景不要开轮询),以及在容器/网络盘上改用 gVisor 类文件系统以减少 inode 事件。
TypeScript 项目要单独处理 tsserver 的内存与文件数:typescript.tsserver.maxTsServerMemory: 4096 提高内存上限,typescript.disableAutomaticTypeAcquisition: true 关闭自动类型获取(会额外拉取 @types 并触发二次索引),typescript.tsserver.useSyntaxServer 可只启用轻量语法服务器。
编辑器层面还有两个常被忽略的开关:editor.codeLens: false 与 editor.minimap.enabled: false 能明显降低大文件渲染压力;files.hotExit 保持默认开启,避免关窗时序列化未保存状态造成假卡顿。改完设置后执行一次 Developer: Reload Window 让索引重建,再对比 Developer: Toggle Performance 的读数。
// 大仓库 settings.json
{
"files.watcherExclude": {
"**/.git/objects/**": true,
"**/node_modules/**": true,
"**/dist/**": true,
"**/build/**": true,
"**/.next/**": true
},
"files.watcherUsePolling": false,
"typescript.tsserver.maxTsServerMemory": 4096,
"typescript.disableAutomaticTypeAcquisition": true,
"editor.codeLens": false,
"editor.minimap.enabled": false,
"files.hotExit": "onExitOnly",
"search.followSymlinks": false
}