使用二分法解决扩展问题
2021 年 2 月 16 日,由 Johannes Rieken 撰写,@johannesrieken
“就像 git-bisect 一样,但用于 VS Code 扩展。”
Visual Studio Code 的真正强大之处在于其扩展:主题扩展添加颜色和图标,语言扩展启用智能代码补全 (IntelliSense) 和导航,调试器扩展让您可以运行代码并轻松查找错误。有的扩展可以播放音乐,有的显示股票行情,还有的可以实现跨地点和时区的协作。VS Code 的市场托管了 28,000 多个扩展,用户安装 50 个或更多扩展的情况并不少见。有这么多扩展,错误是不可避免的。我们不想否认这些问题,而是希望让故障排除变得容易。
“糟糕的”扩展
我们热爱扩展,也并不认为有什么“糟糕的”扩展。然而,和所有软件一样,扩展也有 bug 和功能缺失。所以,为了阅读方便和制造一点人为的戏剧性,我们使用“糟糕的扩展”这个术语,它指的是可能崩溃或只是表现出不希望行为的扩展。幸运的是,我们在设计 VS Code 时考虑到了“糟糕的”扩展,因此在单独的进程中运行它们。这种隔离保证了 VS Code 会持续运行,光标始终闪烁,并且您可以随时保存工作。
为了好玩,也为了更方便地演示扩展二分法,我们创建并发布了 Extension Bisect Demo 扩展。安装后,每当您遇到“bisect”这个词时,它都会烦人地重置您的光标。您可以使用此扩展来跟着本博客文章进行操作。
通过困难的方式查找“糟糕的”扩展
如今,查找一个“糟糕的”扩展可能容易也可能困难。打开“扩展”视图(⇧⌘X (Windows, Linux Ctrl+Shift+X)),禁用一个扩展,重新加载窗口(开发人员:重新加载窗口),然后检查问题是否仍然存在。如果问题消失了,那么该扩展就是“糟糕的”,您就完成了。否则,重新启用该扩展,并对下一个扩展重复此过程。
如果您幸运,第一个扩展就是“糟糕的”;如果您不幸运,它就是最后一个扩展。用计算机科学的语言来说,这意味着对于 N
个扩展,最坏情况下您需要重复该过程 O(N)
(N 阶),平均情况下是 O(N/2)
。因为此算法由人类(您)操作,所以即使 N
的值很小,也仍然很费力。这就是扩展二分法实用程序派上用场的地方。它在最坏和平均情况下要好得多,因为它将扩展逐半禁用。
欢迎使用扩展二分法
VS Code 中的扩展二分法实用程序灵感来源于 git bisect 命令。对于熟悉 Git 的人来说,这个命令有助于找出仓库中哪个提交引入了问题。
我们用一个示例:我安装了 24 个扩展,其中第 8 个扩展是“糟糕的”。我们知道迭代方法需要 8 步。那么二分法呢?
下面的视频展示了通过帮助:启动扩展二分法命令启动扩展二分法,然后选择现在好了或这有问题,直到识别出“糟糕的”扩展。一旦识别出来,您可以选择报告该扩展的问题。
以下是找到“糟糕的”扩展的步骤
- 二分法将 24 个扩展分成两半,每半 12 个,并禁用后一半的所有 12 个扩展。
- 在此示例中,第 8 个扩展是“糟糕的”那个,所以它在前半部分,没有被禁用。情况仍然不如我们预期的那样好。因为问题仍然存在,扩展二分法重复该过程,将前 12 个扩展分成两部分:6 个启用,6 个禁用。所有其他扩展也都被重新启用。
- 第 8 个扩展现在被禁用了。现在情况好了。这意味着二分法可以在后半部分(扩展 6-11)继续进行,并将它们分成 3 个启用和 3 个禁用扩展。
- 现在,第 8 个扩展被重新启用,问题再次出现。这意味着二分法在前半部分继续进行。它将它们分成 1 个启用和 2 个禁用扩展。
- 第 8 个扩展现在被禁用,情况又好了,二分法在后半部分继续进行,将其分成 1 个启用和 1 个禁用扩展。
- 第 8 个扩展是唯一被禁用的扩展,问题也消失了。这意味着我们找到了“糟糕的”扩展,并且我们完成了。
更快地排除故障
我们看到,在每一步中,二分法都将搜索空间减半。现在它以对数时间运行,导致平均和最坏情况下的性能为 O(log N)
。这非常好,因为它具有良好的可伸缩性。对于 24 个扩展,您需要 4 到 5 步才能找到“糟糕的”扩展;对于 38 个扩展,只需再多一步。然而,最好的情况反而更糟,因为使用迭代方法,您可能会很幸运地在第一轮就找到“糟糕的”扩展。
请记住,扩展二分法依赖于您给出正确的反馈。您可以通过始终回答现在好了(会归咎于最后一个扩展)或这有问题(不会找到任何扩展)来轻易地欺骗它,也欺骗自己。
另一个有用的见解是,扩展二分法在开始时会考虑所有已启用的扩展列表。这意味着您可以通过在开始前禁用已知“良好”的扩展,并在之后重新启用它,从而将其排除在二分法之外。但是,只有当您确定该扩展不是“糟糕的”那个时才这样做。
最后,您可能会注意到二分法多花了一步(log2(N) + 1
)。那是因为它在第一轮开始时会禁用所有扩展。执行这第一步是因为您可能遇到的问题是由 VS Code 本身引起的,而不是由扩展引起的,我们不想让您不必要地陷入困境。
就是这样。我们希望您永远不需要使用扩展二分法。但是,如果您确实遇到可能与扩展相关的问题,那么我们希望我们能让故障排除更轻松、更快、更愉快。
编程愉快,
Johannes Rieken,VS Code 首席软件工程师 @johannesrieken