バイセクトで拡張機能の問題を解決する
2021年2月16日 ヨハネス・リーケン (@johannesrieken)
"git-bisect のように、VS Code の拡張機能版です。"
Visual Studio Code の真の力は、その拡張機能にあります。テーマ拡張機能は色やアイコンを追加し、言語拡張機能はスマートなコード補完 (IntelliSense) やナビゲーションを可能にし、デバッガー拡張機能はコードを実行してバグを簡単に見つけられるようにします。音楽を再生する拡張機能、株価を表示する拡張機能、複数の場所やタイムゾーンで共同作業を可能にする拡張機能もあります。VS Code のマーケットプレイスには28,000以上の拡張機能があり、ユーザーが50以上の拡張機能をインストールしていることも珍しくありません。これほど多くの拡張機能があれば、バグは避けられません。私たちは否定するのではなく、トラブルシューティングを簡単にしたいと考えています。
"問題のある" 拡張機能
私たちは拡張機能が大好きで、本当に「問題のある」拡張機能があるとは思っていません。しかし、すべてのソフトウェアと同様に、拡張機能にはバグや機能不足があります。そこで、読みやすさと人為的なドラマのために、「問題のある拡張機能」という言葉を使ってみましょう。これは、クラッシュしたり、単に望ましくない動作を示したりする可能性のある拡張機能です。幸いなことに、私たちは「問題のある」拡張機能を念頭に置いて 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個ずつの2つの半分に分割し、後半の12個の拡張機能をすべて無効にします。
- この例では、8番目の拡張機能が「問題のある」ものであり、前半に含まれるため無効にされていません。まだ期待通りに動作していません。まだ問題があるため、拡張機能のバイセクトはプロセスを繰り返し、最初の12個の拡張機能を2つの部分に分割します。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自体が原因で問題が発生している可能性があるため行われ、不必要に袋小路に送ることを望まないためです。
以上です。拡張機能のバイセクトを一度も使用する必要がないことを願っています。ただし、拡張機能に関連する可能性のある問題に遭遇した場合は、トラブルシューティングをより簡単、迅速、そして快適にできることを願っています。
ハッピーコーディング、
ヨハネス・リーケン、VS Code プリンシパルソフトウェアエンジニア @johannesrieken