在 VS Code 中试试

使用 bisect 解决扩展问题

2021 年 2 月 16 日 作者 Johannes Rieken, @johannesrieken

“就像 git-bisect 一样,但适用于 VS Code 扩展。”

Visual Studio Code 的真正强大之处在于它的扩展:主题扩展添加颜色和图标,语言扩展提供智能代码补全 (IntelliSense) 和导航,调试器扩展让你运行代码并轻松查找错误。还有播放音乐的扩展,显示股票行情的扩展,以及支持跨地点和时区协作工作的扩展。VS Code 市场拥有超过 28,000 个扩展,用户安装 50 个或更多扩展是很常见的事情。如此多的扩展,bug 是不可避免的。我们希望让故障排除变得容易,而不是回避问题。

“不良”扩展

我们喜欢扩展,并且不认为真的存在任何“不良”扩展。然而,像所有软件一样,扩展也存在 bug 和功能缺陷。因此,为了阅读方便和一些人为的戏剧性,我们使用“不良扩展”这个术语,它指的是可能崩溃或仅仅表现出意外行为的扩展。幸运的是,我们在设计 VS Code 时考虑到了“不良”扩展,因此将它们运行在独立的进程中。这种隔离保证了 VS Code 持续运行,光标始终闪烁,并且你始终可以保存你的工作。

为了好玩,也为了更容易演示扩展二分查找,我们创建并发布了 Extension Bisect Demo 扩展。安装后,每当你输入“bisect”这个词时,它会恼人地重置你的光标。你可以使用这个扩展来跟随这篇博客文章的讲解。

用困难的方式寻找“不良”扩展

今天,寻找“不良”扩展可能容易也可能困难。打开“扩展”视图(⇧⌘X(Windows、Linux 为 Ctrl+Shift+X),禁用一个扩展,重载窗口(开发者:重载窗口),然后检查问题是否仍然存在。如果问题消失了,那么那个扩展就是“不良”扩展,你就完成了。否则,重新启用该扩展,然后对下一个扩展重复此过程。

Disabling an extension step by step

如果你走运,第一个扩展就是“不良”扩展;如果你不走运,那就是最后一个扩展。用计算机科学的语言来说,这意味着如果有 N 个扩展,你最坏情况下需要重复该过程 O(N) 次(N 的数量级),平均情况下需要 O(N/2) 次。由于这个算法是由人类(你)来操作的,即使 N 的值很小,也相当费力。这时,扩展二分查找工具就派上用场了。它在最坏和平均情况下的表现都要好得多,因为它通过每次禁用一半扩展来工作。

欢迎使用扩展二分查找

VS Code 中的扩展二分查找工具灵感来源于 git bisect 命令。对于熟悉 Git 的人来说,这个命令有助于找出仓库中哪个提交引入了问题。

让我们举个例子:我安装了 24 个扩展,其中第 8 个扩展是“不良”的。我们知道迭代方法需要 8 个步骤。那二分查找呢?

下方的视频展示了如何通过 帮助:启动扩展二分查找 命令启动扩展二分查找,然后选择 现在好了仍有问题,直到识别出“不良”扩展。一旦识别出来,你可以选择为该扩展报告问题。

The extension bisect process

以下是逐步演示如何找到“不良”扩展

  1. 二分查找将 24 个扩展分成两半,每半 12 个扩展,并禁用后一半的全部 12 个扩展。
  2. 在这个例子中,第 8 个扩展是“不良”扩展,所以它在前半部分且未被禁用。情况仍然不像我们期望的那样好。因为问题仍然存在,扩展二分查找会重复该过程,将前 12 个扩展分成两部分:6 个启用,6 个禁用。所有其他扩展也会被重新启用。
  3. 现在,第 8 个扩展被禁用了。情况现在好了。这意味着二分查找可以继续处理后半部分(扩展 6-11),并将它们分成 3 个启用和 3 个禁用的扩展。
  4. 现在,第 8 个扩展被重新启用了,问题又出现了。这意味着二分查找继续处理前半部分。它将它们分成 1 个启用和 2 个禁用的扩展。
  5. 第 8 个扩展现在被禁用了,情况又好了,二分查找继续处理后半部分,将其分成 1 个启用和 1 个禁用的扩展。
  6. 第 8 个扩展是唯一被禁用的扩展,问题消失了。这意味着我们找到了“不良”扩展,并且我们完成了。

更快地排除故障

我们看到,在每一步中,二分查找将搜索空间减半。现在它以对数时间运行,导致平均和最坏情况下的性能为 O(log N)。这非常好,因为它具有良好的可伸缩性。对于 24 个扩展,你需要 4 到 5 个步骤来找到“不良”扩展;对于 38 个扩展,只需再多一个步骤。然而,最好情况下的性能反而更差,因为使用迭代方法,你可能运气好在第一轮就找到“不良”扩展。

请记住,扩展二分查找依赖于你给出正确的反馈。你可以通过始终回答 现在好了(会将问题归咎于最后一个扩展)或 仍有问题(将找不到扩展)来轻易地欺骗它,以及你自己。

另一个有用的提示是,扩展二分查找开始时会考虑所有已启用的扩展。这意味着你可以通过在开始前禁用一个已知“良好”的扩展并在之后重新启用它来将其排除在二分查找之外。但是,只有在你确定该扩展不是“不良”扩展时才这样做。

最后,你可能会注意到二分查找会多花一个步骤(log2(N) + 1)。这是因为它在第一轮中会禁用所有扩展。执行此第一步是为了应对你遇到的问题可能是由 VS Code 本身而非扩展引起的,这样我们就不必让你不必要地进行二分查找。

就是这样。我们希望你永远不需要使用扩展二分查找。但是,如果你确实遇到了可能与某个扩展相关的问题,我们希望我们可以让故障排除变得更容易、更快、更愉快。

祝你编程愉快,

Johannes Rieken,VS Code 首席软件工程师 @johannesrieken