Bisect を使用した拡張機能の問題の解決
2021年2月16日 by Johannes Rieken, @johannesrieken
「VS Code 拡張機能版の git-bisect です。」
Visual Studio Code の真の力はその拡張機能にあります。テーマ拡張機能は色やアイコンを追加し、言語拡張機能はスマートなコード補完 (IntelliSense) やナビゲーションを可能にし、デバッガー拡張機能はコードを実行して簡単にバグを見つけることを可能にします。音楽を再生する拡張機能、株価を表示する拡張機能、場所やタイムゾーンを越えて共同作業を可能にする拡張機能もあります。VS Code の Marketplace には 28,000 以上の拡張機能が公開されており、ユーザーが 50 以上の拡張機能をインストールしていることも珍しくありません。これだけ多くの拡張機能があれば、バグは避けられません。それを否定するのではなく、トラブルシューティングを簡単にしたいと考えています。
「悪い」拡張機能
私たちは拡張機能が大好きで、「悪い」拡張機能は実際にはないと考えています。しかし、すべてのソフトウェアと同様に、拡張機能にもバグや機能の欠落があります。そこで、読みやすさと人為的なドラマのために、「悪い拡張機能」という言葉を使いましょう。これは、クラッシュしたり、単に望ましくない動作を示したりする可能性のある拡張機能のことです。幸いなことに、私たちは「悪い」拡張機能を念頭に置いて VS Code を設計したため、それらを別のプロセスで実行します。この分離により、VS Code が実行し続け、カーソルが常に点滅し、いつでも作業を保存できることが保証されます。
楽しんで、そして拡張機能の bisect のデモを簡単にするために、私たちは Extension Bisect Demo 拡張機能を作成し、公開しました。インストールすると、「bisect」という単語に到達するたびに、カーソルが煩わしくリセットされます。この拡張機能を使って、このブログ記事に沿って進めることができます。
「悪い」拡張機能を見つける従来の方法
今日、「悪い」拡張機能を見つけるのは簡単でもあり、難しくもあります。拡張機能ビュー (⇧⌘X (Windows、Linux Ctrl+Shift+X)) を開き、拡張機能を無効にし、ウィンドウをリロード (Developer: Reload Window) して、問題がまだ存在するかどうかを確認します。問題がなければ、その拡張機能が「悪い」ものであり、作業は完了です。そうでなければ、拡張機能を再度有効にし、次の拡張機能でプロセスを繰り返します。
運が良ければ、最初の拡張機能が「悪い」ものです。運が悪ければ、最後の拡張機能です。コンピューターサイエンスの言葉を使うと、これは N
個の拡張機能がある場合、最悪ケースでは O(N)
(オーダー N)、平均ケースでは O(N/2)
でプロセスを繰り返すことを意味します。このアルゴリズムは人間 (あなた) によって操作されるため、N
の値が小さくても骨が折れます。ここで役立つのが extension bisect ユーティリティです。これは拡張機能を半分ずつ無効にするため、最悪および平均ケースでははるかに優れています。
Extension bisect のご紹介
VS Code の Extension bisect ユーティリティは、git bisect コマンドから着想を得ています。Git に詳しい方なら、このコマンドがリポジトリのどのコミットで問題が発生したかを特定するのに役立つことをご存知でしょう。
例を使ってみましょう。私は 24 個の拡張機能をインストールしており、8 番目の拡張機能が「悪い」ものです。反復的なアプローチでは 8 つのステップが必要であることがわかっています。bisect はどうでしょうか?
下のビデオは、Help: Start Extension Bisect コマンドで extension bisect を開始し、「悪い」拡張機能が特定されるまで Good now または This is bad を選択する様子を示しています。特定されると、その拡張機能の問題を報告するオプションが表示されます。
「悪い」拡張機能がどのように見つけられたかのステップバイステップです
- Bisect は 24 個の拡張機能をそれぞれ 12 個の拡張機能からなる 2 つの半分に分割し、後半の 12 個の拡張機能をすべて無効にします。
- このサンプルでは、8 番目の拡張機能が「悪い」ものなので、それは前半に含まれており無効化されません。まだ期待どおりに動作していません。まだ問題があるため、extension bisect はプロセスを繰り返し、最初の 12 個の拡張機能を 2 つの部分に分割します。6 個が有効になり、6 個が無効になります。他のすべての拡張機能も再度有効になります。
- 8番目の拡張機能は現在無効化されています。これで正常に動作するようになりました。つまり、bisect は後半(拡張機能 6-11)に進み、それらを3つの有効な拡張機能と3つの無効な拡張機能に分割できます。
- ここで、8 番目の拡張機能が再度有効になり、問題が再発しました。これは、bisect が前半に進むことを意味します。bisect はそれらを 1 つの有効な拡張機能と 2 つの無効な拡張機能に分割します。
- 8番目の拡張機能は現在無効化されており、再び正常に動作するようになりました。bisectは後半に進み、それを1つの有効な拡張機能と1つの無効な拡張機能に分割します。
- 8 番目の拡張機能だけが無効になり、問題はなくなりました。これは、「悪い」拡張機能を見つけたことを意味し、これで完了です。
より速いトラブルシューティング
各ステップで、bisect が検索範囲を半分に減らしていくことがわかります。これにより、ステップは対数時間で実行され、平均および最悪ケースのパフォーマンスは O(log N)
になります。これはスケーラビリティに優れているため、非常に良いことです。24 個の拡張機能があれば、「悪い」拡張機能を見つけるのに 4〜5 ステップで済み、38 個の拡張機能でも、わずか 1 ステップ増えるだけです。しかし、最良ケースでは反復的なアプローチの方が悪くなります。なぜなら、そのアプローチでは運が良ければ最初のラウンドで「悪い」ものを見つけることができるからです。
extension bisect は、あなたが正しいフィードバックを与えることに依存していることを覚えておいてください。常に Good now (最後の拡張機能のせいにする) または This is bad (拡張機能を見つけられない) と答えることで、簡単にそれを、そしてあなた自身をだますことができます。
もう一つの有用な洞察は、extension bisect が有効な拡張機能の全リストを考慮して開始するということです。つまり、既知の「良い」拡張機能を開始前に無効にし、終了後に再度有効にすることで、bisect から除外することができます。ただし、その拡張機能が「悪い」ものではないと確信している場合にのみ行ってください。
最後に、bisect が 1 ステップ余分にかかっている (log2(N) + 1
) ことに気づくかもしれません。これは、最初のラウンドですべての拡張機能を無効にすることから始めるためです。この最初のステップは、あなたが見ている問題が拡張機能ではなく VS Code 自体によって引き起こされている可能性があり、不必要にあなたを混乱させたくないために行われます。
以上です。私たちは、あなたが extension bisect を使う必要がないことを願っています。しかし、もし拡張機能に関連する可能性のある問題に遭遇した場合は、トラブルシューティングをより簡単、迅速、そして快適にできることを願っています。
ハッピーコーディング、
Johannes Rieken, VS Code プリンシパルソフトウェアエンジニア @johannesrieken