尝试以扩展 VS Code 中的代理模式!

使用二分法解决扩展问题

2021年2月16日,由 Johannes Rieken (@johannesrieken) 发布

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

Visual Studio Code 的真正力量在于它的扩展:主题扩展添加颜色和图标,语言扩展支持智能代码补全 (IntelliSense) 和导航,调试器扩展使您能够运行代码并轻松找到错误。有的扩展可以播放音乐,有的可以显示股票行情,还有的扩展支持跨地域和时区的协作。VS Code Marketplace 上有超过 28,000 个扩展,用户安装 50 个或更多的扩展并不少见。有如此多的扩展,出现错误是不可避免的。我们不想否认这一点,而是希望让故障排除变得简单。

“坏”扩展

我们热爱扩展,并且不认为真的有任何“坏”扩展。然而,像所有软件一样,扩展也存在错误和功能缺陷。因此,为了便于阅读和增加戏剧性,我们使用“坏扩展”这个术语,它指的是可能崩溃或只是表现出不期望行为的扩展。幸运的是,我们在设计 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