使用二分法解決擴充功能問題
2021 年 2 月 16 日,Johannes Rieken,@johannesrieken
「就像 git-bisect,但用於 VS Code 擴充功能。」
Visual Studio Code 的真正威力在於其擴充功能:主題擴充功能新增色彩和圖示,語言擴充功能啟用智慧程式碼完成 (IntelliSense) 和導覽,偵錯工具擴充功能讓您能夠執行程式碼並輕鬆找到錯誤。有些擴充功能可以播放音樂,有些可以顯示股票行情,還有一些擴充功能可以實現跨地點和時區的協同工作。VS Code 市集託管超過 28,000 個擴充功能,使用者安裝 50 個或更多擴充功能並不罕見。有這麼多擴充功能,錯誤是不可避免的。我們不採取否認的態度,而是希望讓疑難排解變得容易。
「不良」擴充功能
我們喜愛擴充功能,而且真的不認為有任何「不良」擴充功能。然而,就像所有軟體一樣,擴充功能也存在錯誤和功能缺口。因此,為了方便閱讀和增加戲劇效果,我們使用「不良擴充功能」一詞,指的是可能會當機或只是顯示非預期行為的擴充功能。幸運的是,我們在設計 VS Code 時就考慮到「不良」擴充功能,因此將它們在獨立的程序中執行。這種隔離機制保證 VS Code 持續運作,游標始終閃爍,而且您始終可以儲存您的工作。
為了好玩,並為了更容易示範擴充功能二分法,我們建立並發布了 擴充功能二分法示範擴充功能。安裝後,每當您輸入「bisect」這個字詞時,它都會惱人地重設您的游標。您可以使用此擴充功能來跟著這篇部落格文章的步驟操作。
以困難的方式尋找「不良」擴充功能
現今,尋找「不良」擴充功能可能很容易也可能很困難。開啟「擴充功能」檢視 (⇧⌘X (Windows、Linux Ctrl+Shift+X)),停用擴充功能,重新載入視窗 (開發人員:重新載入視窗),並檢查問題是否仍然存在。如果問題消失,則表示該擴充功能是「不良」的,您就完成了。否則,重新啟用該擴充功能,並對下一個擴充功能重複此過程。
如果您幸運,第一個擴充功能就是「不良」的;如果您不幸,則是最後一個擴充功能。使用電腦科學語言來說,這表示若有 N
個擴充功能,您在最糟情況下需要重複此過程 O(N)
(order 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 個擴充功能,只需要多 1 個步驟。然而,最佳情況更糟,因為使用迭代方法,您可能會很幸運地在第一輪就找到「不良」擴充功能。
請記住,擴充功能二分法依賴您提供正確的回饋。您可能會因為始終回答 現在正常 (歸咎於最後一個擴充功能) 或 這很糟糕 (找不到擴充功能) 而輕易地愚弄它和您自己。
另一個有用的見解是,擴充功能二分法一開始會考慮已啟用擴充功能的完整清單。這表示您可以透過在開始之前停用已知的「良好」擴充功能,並在之後重新啟用它,將其從二分法中排除。但是,僅當您確定該擴充功能不是「不良」的擴充功能時才執行此操作。
最後,您可能會注意到二分法需要額外一個步驟 (log2(N) + 1
)。這是因為它在第一輪開始時停用所有擴充功能。執行此第一步的原因是您可能會看到由 VS Code 本身而非擴充功能引起的問題,我們不希望不必要地讓您陷入困境。
就是這樣。我們希望您永遠不需要使用擴充功能二分法。但是,如果您確實遇到可能與擴充功能相關的問題,那麼我們希望我們能讓疑難排解變得更輕鬆、更快速、更愉快。
祝您編碼愉快,
Johannes Rieken,VS Code 首席軟體工程師 @johannesrieken