JetBrains详解Rider与ReSharper启动缓慢原因:微软帮助优化Defender扫描
当我们发布 ReSharper 的进程外(OOP)架构 时,用户报告称,在 Windows 上使用 ReSharper 的 IDE 启动时间变慢了。经过性能分析,原因让我们感到很意外:Microsoft Defender 扫描我们进程所花的时间比预期更长。这篇文章会介绍我们的发现、我们与微软合作中学到的经验,以及我们构建的一个工具,它能让其他人也能开展同样的调查。
启动性能中的一个意外因素
多年来,工具性能一直是我们从用户那里收到的反馈中最核心的话题。我们的遥测数据和用户调查证实了许多人一直在反馈的情况:尽管 ReSharper 功能很强大,但它对 Visual Studio 响应速度的影响已经干扰到了你们的日常开发流程。这促使我们着手开发新的进程外(OOP)架构。我们去年首次正式公开发布了 OOP 模式。(现在,得益于这些调查,从 2026.2.1 版本开始,它已默认启用。)总体来看,我们的遥测数据表明性能有所改善。然而,某一时刻我们注意到了一个意外情况——有客户开始报告启动时间变慢。经过几轮性能分析,收集到的数据指向了一个意想不到的延迟来源:Microsoft Defender。
事实证明,位于受写保护路径中的进程会获得更广泛的信任规则。Microsoft Defender 在启动时几乎不会扫描这些进程——即使 ReSharper 从用户安装目录加载系统 DLL,扫描也只需要几秒钟。但一旦 ReSharper 开始作为独立进程运行,Defender 就会对其进行完整扫描,使首次启动时间增加数十秒(见下图)。
[LOADING...] ReSharper 进程内与进程外对比
这激起了我们的好奇心,也让我们一头扎进了这个问题。我们开始分析数十款开发工具的 Microsoft Defender ETW(Windows 事件跟踪)日志,结果非常惊人:有些工具在启动时会被扫描 30 秒以上,而另一些不到一秒钟就能完成扫描,正如我们上面观察到的那样。我们自然想弄清楚这背后的原因,并找到加速 JetBrains 工具启动的方法。这是一项雄心勃勃的项目,但我们愿意接受挑战!
我们首先需要建立一个可重复的测量流程。这样,我们才能与 JetBrains 内部的其他团队,以及微软的同事分享,并展开富有成效的对话。我们非常感谢微软团队的所有解释、他们的开放态度,以及他们协助我们开展这项调查的意愿。
衡量影响
我们通过两种方式跟踪 Microsoft Defender 的活动:Microsoft Defender ETW 日志(如前面所提)和直接 CPU 时间测量。我们发现,在我们的场景中,这两种方法的结果大致相当。如果你对两者的区别感兴趣,请参阅我们的 GitHub 说明。
Microsoft Defender 与 Windows 的许多其他组件一样,使用 ETW。它会在 Microsoft-Antimalware-Engine 提供程序下发出事件。微软提供了一个用于 Defender 相关性能调查的 PowerShell 模块,该模块使用的就是这个提供程序。它包含两个 cmdlet:New-MpPerformanceRecording 用于收集跟踪记录,Get-MpPerformanceReport 用于分析结果。
在我们的场景中,大多数变慢都来自 Microsoft Defender 的扫描事件。Microsoft-Antimalware-Engine/StreamScanRequestTask ETW 事件会报告每次扫描的 开始 和 结束 时间,表示 Defender 在真实经过时间内扫描该数据流所花费的时间。我们收集到的数据清楚地显示了 Defender 如何影响我们工具启动时的实际耗时(wall time)。
方法
性能测量在一台配备 Intel Core Ultra 9 285H(16 核)处理器和 64 GB DDR5 内存的 Dell Pro Max 16(MA16250)笔记本电脑上进行。宿主机运行的是 Windows 11 Pro。工作负载在配置为 8 个 vCPU 和 8 GB 静态内存的 Hyper-V 虚拟机中执行。每个工具测量 10 次。
按照性能测量时的标准最佳实践,我们在每次测量前都会重启虚拟机,以模拟冷启动。这样可以减少文件和内存缓存对我们观察到的结果的影响。
下图显示了平均扫描时间,并带有标准差误差线。
实验结果
[LOADING...] [LOADING...] [LOADING...] [LOADING...]
如你所见,我们测量了多种开发工具,Defender 对它们的扫描时间存在明显差异:
- JetBrains 系列 IDE(以及其他部分编辑器类工具)在冷启动时大约需要 10 到 40 秒的扫描时间,而微软的 IDE 和其他多种编辑器的扫描时间则可以忽略不计(都不到 1 秒)。
- 基于 CLI 的工具(命令行代理)的扫描时间大约在 2 秒以内,这可能是因为它们是体积小、结构简单的二进制文件,包含的 DLL 很少。
与微软的合作以及我们的解决方案
即使我们已经构建了一个工具来测量 Microsoft Defender 的影响,我们仍然没有完全理解 Defender 的扫描原理。我们也查阅了他们的文档,但没有找到答案。于是我们直接联系了微软的同事!
他们帮助我们理解了哪些参数会导致 Microsoft Defender 执行更多工作。一个核心原则是:位于受写保护文件夹中的文件可以获得扫描优化。
这时,我们重新审视了安装和启动工具的各种方式,试图找到减少扫描时间的办法。一个观察结果是,JetBrains Rider 受到的扫描甚至比 IntelliJ IDEA 和 ReSharper 加起来还要密集。我们当时也不清楚原因,于是再次请求微软团队协助。他们针对这个具体案例在自己的侧进行了优化,并在 1.449.454.0 版本中发布了 Defender 的调整。现在,当 ReSharper OOP 和 JetBrains Rider 安装到受写保护目录时,它们也能获得扫描性能提升:
[LOADING...]
JetBrains Toolbox 会将软件安装到 %LOCALAPPDATA%\Programs 目录中。由于该目录在写入时不需要提升权限,Toolbox 可以无缝更新软件,但如上图所示,它无法获得受写保护目录所带来的性能提升。
正如我们之前报道过的那样,Rider 本身会在安装过程中将某些目录排除在 Microsoft Defender 扫描之外(更多信息请见此处)。它使用 Add-MpPreference PowerShell cmdlet 帮助你自动配置 Microsoft Defender 排除项。我们仍在评估如何以最佳方式支持通过 JetBrains Toolbox 安装 Rider 时的 Microsoft Defender 排除配置。你可以通过我们的 TBX-2851 问题 跟踪进度。
注意:在托管环境中,管理员可以禁用或阻止本地添加排除项的功能。
测量你自己的工具
如果你自己的工具也出现了启动缓慢的问题,那么分析是否是 Microsoft Defender 影响了它,无疑是很有意义的。为了帮助你调查,我们发布了我们自己内部使用的工具——小巧且易于使用的 Defender Performance Tool。源代码和发布版本可在 GitHub 上获取。
[LOADING...] Defender Performance Tool 截图
你可以用它做以下几件事:
- 实时观察应用程序在启动、加载插件或执行编译时的扫描活动。
- 打开通过 New-MpPerformanceRecording 离线录制的快照,以便调查另一台机器上的跟踪数据(例如客户收集的数据)。
- 在加载多个快照后导出 CSV 文件,用于进一步分析。
希望这能帮助你进行类似的调查。如果你有任何有趣的发现,欢迎告诉我们!
结论
如你所见,Microsoft Defender 可能对工具性能产生很大的影响。我们在这个领域与微软合作的过程中学到了很多,也希望我们的发现能帮助开发者和软件供应商了解如何通过观察和调整 Microsoft Defender 的行为,来最好地维护其 Windows 系统的安全性。
与 Microsoft Defender 协作时的一些最佳实践总结:
- 保持 Microsoft Defender 的病毒库定义为最新。
- 使用微软提供的 Defender 相关性能调查 PowerShell 模块。
- 试用我们用于分析 Microsoft Defender 日志的新工具,可在 GitHub 上获取。
- 通过将软件安装到受写保护目录来优化 Microsoft Defender 的扫描。
- 如有需要,使用 Add-MpPreference PowerShell cmdlet 自动配置 Microsoft Defender 排除项。
- 在你的 Windows 机器上设置 DevDrive,用于存放代码仓库和软件包缓存。
希望你在自己的工作流程中也已经注意到了 ReSharper 和 Rider 的这些改进!ReSharper 2026.2.1 现已默认启用 OOP。今天就试试吧!