现已发布!阅读关于 11 月新增功能和修复的内容。

使用二分法解决扩展问题

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

“就像 git-bisect 一样,但是是针对 VS Code 扩展的。”

Visual Studio Code 的真正强大之处在于它的扩展:主题扩展增加颜色和图标,语言扩展支持智能代码补全 (IntelliSense) 和导航,调试器扩展让你能够运行代码并轻松找到 bug。还有播放音乐的扩展,显示股票行情的扩展,以及支持跨地点和时区协同工作的扩展。VS Code Marketplace 托管着超过28,000个扩展,用户安装50个或更多扩展的情况并不少见。有如此多的扩展,bug 在所难免。我们不想否认它的存在,而是希望让故障排除变得容易。

“不良”扩展

我们热爱扩展,并不认为真的存在什么“不良”扩展。然而,像所有软件一样,扩展也有 bug 和功能缺失。因此,为了方便阅读和制造一点人为的戏剧性,我们姑且使用“不良扩展”这个词,它指的是可能会崩溃或简单地显示不需要行为的扩展。幸运的是,我们在设计 VS Code 时考虑到了“不良”扩展,因此它们运行在独立的进程中。这种隔离保证了 VS Code 能够持续运行,光标始终闪烁,并且你始终可以保存你的工作。

为了好玩,也为了更容易演示扩展二分法,我们创建并发布了Extension Bisect Demo 扩展。安装后,每当你输入到“bisect”这个词时,它就会烦人地重置你的光标。你可以使用这个扩展来跟着这篇博文一起操作。

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

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

Disabling an extension step by step

如果你幸运,第一个扩展就是“不良”的;如果你不幸,则是最后一个。用计算机科学的语言来说,这意味着对于 N 个扩展,最坏情况下你需要重复该过程 O(N)(N 阶),平均情况下是 O(N/2)。因为这个算法是由人(你)操作的,即使 N 的值很小,也仍然很费力。这就是扩展二分法工具派上用场的地方。它在最坏和平均情况下要好得多,因为它通过减半的方式禁用扩展。

欢迎使用扩展二分法

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

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

下面的视频展示了如何通过 Help: Start Extension Bisect 命令启动扩展二分法,然后选择 Good nowThis is bad,直到识别出“不良”扩展。一旦识别出来,你就可以选择为该扩展报告问题。

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个扩展,只需要多1步。然而,最佳情况会更糟,因为使用迭代方法,你可能运气好在第一轮就找到“不良”扩展。

请记住,扩展二分法依赖于你提供正确的反馈。你可以很容易地骗过它,也骗过你自己,方法是总是回答 Good now(会归咎于最后一个扩展)或 This is bad(将找不到任何扩展)。

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

最后,你可能会注意到二分法多花了一个步骤(log2(N) + 1)。那是因为它在第一轮中禁用了所有扩展。执行这第一步是因为你可能遇到的问题是由 VS Code 本身而非扩展引起的,我们不想不必要地将你引入歧途。

就这样。我们希望你永远不需要使用扩展二分法。然而,如果你确实遇到了可能与扩展相关的问题,那么我们希望我们能让故障排除变得更简单、更快、更愉快。

编程愉快,

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

© . This site is unofficial and not affiliated with Microsoft.