Transcript
00:00:00TypeScript 7が正式にリリースされました。1年以上の苦心した開発を経て
00:00:05コンパイラをGoに移植したことで、AIを使えばすべて解決できると証明されたので、
00:00:10開発者の皆さんもきっと喜んでいるはずです。今 `npm install typescript` を実行すると、
00:00:16Goコンパイラを搭載したバージョン7がインストールされます。数日前のMicrosoftの発表動画を受けて、
00:00:20どのようにしてこれほどの劇的なパフォーマンス向上を実現したのか、詳しく見ていきたいと思います。
00:00:25その結果は本当に目を見張るものがあります。新コンパイラはVS Codeのコードベース
00:00:31(約8,000ファイル、130万行)を、旧コンパイラの125秒に対して
00:00:39わずか10秒でビルドします。そして、TypeScriptがGitHubで堂々の1位の言語となった今、
00:00:44信じられないかもしれませんが、この新コンパイラは多くの人々の生活を変えるでしょう。考えるだけで感無量になります。
00:00:49ですが、バージョン6と7でほぼ同じ機能を見るよりも、
00:00:54そのパフォーマンスがどのように実現されたかを掘り下げたいと思います。では、新コンパイラを見てみましょう。
00:00:59何がこれほど高速化させているのでしょうか?そもそも、なぜ書き直したのでしょうか?C#の生みの親であり、Microsoftのテクニカルフェローである
00:01:09アンダース・ヘイルスバーグ氏は端的に語っています。JavaScriptはUIやブラウザ向けに最適化されており、
00:01:16計算集約的なワークフローやコンパイラには最適化されていません。シングルスレッドであるため、その理由は明解です。
00:01:22抽象構文木の処理や型チェックなどは、単一コアへのアクセスでは限界があります。
00:01:27技術的にはワーカーに処理を分散させることもできますが、データのシリアライズとデシリアライズが必要になり、
00:01:32遅くメモリ消費も大きくなります。さらに、それら全体の管理の複雑さにも対処しなければなりません。
00:01:38そこで彼らは、目的に適した言語であるGoを採用し、劇的なパフォーマンス向上を果たしました。
00:01:43Goはコンパイル言語であるため、コードを解釈することなくCPU上で直接実行できます。
00:01:48また、Goは非常に優れた並列処理モデルを備えており、複数の実行スレッドを
00:01:54共有メモリを用いて同時に簡単に実行できます。つまり、1つのコアだけでなく、
00:02:00マシン上のすべてのコアを活用できるということです。高速化の要因はおよそ半々で、
00:02:06最大で半分はネイティブコードであること、残りは共有メモリによる並列処理によるものです。
00:02:12Goはまさにこれに最適な言語です。単にGoが速いというだけでなく、
00:02:17課題に投入できるリソースそのものが増えており、その結果がすべてを物語っています。
00:02:23数値を見てみると、130万行のVS Codeは、旧コンパイラで125.7秒かかっていたのが
00:02:3210.6秒になり、11.9倍の向上です。Blueskyでは24.3秒から2.8秒へと8.7倍の向上、
00:02:42Playwrightでは12.8秒から1.5秒へと8.7倍向上しています。面白いことに、Better Stackに登録するのもわずか1秒しかかかりません。
00:02:49コアの単体性能が以前ほど伸びなくなっているため、この差は広がる一方です。
00:02:54ですが、コアの数自体は増えています。例えば私が使っているM3 Maxは14コアもあり、驚異的です。
00:03:00大学時代に自作したゲーミングPCのIntel i7は4コアで、当時は化け物だと思っていました。
00:03:06JavaScriptコンパイラはそのうち1つのコアしか使いませんが、Goなら全コアを解放できます。
00:03:11当然、コア数が多いほどパフォーマンスが高くなります。このマシンで大規模プロジェクトをバージョン6でコンパイルすると
00:03:1745秒かかりますが、バージョン7ならわずか3秒まで短縮できます。
00:03:24コンパイルプロセスには複数のフェーズがあり、型チェックはその1つに過ぎません。
00:03:29Goは4つの型チェッカーを立ち上げ、それぞれがコードベースの4分ノ1ずつをチェックします。
00:03:34しかし、それをさらに改善することも可能です。コンパイル時にチェッカー数を12に設定すれば、
00:03:39さらに高速なパフォーマンスが得られます。VS Codeのリポジトリをダウンロードしたので、TypeScript 7と6の違いを見てみましょう。
00:03:45デフォルトで私のマシンの `tsc` はTypeScript 7を指しているので、診断を実行してみます。
00:03:515.4秒かかったのがわかります。時間の大部分は型チェックに費やされており、
00:03:57そのうち4.7秒を占めています。これもさらにスピードアップできます。
00:04:02`checkers 12` というフラグを追加すると、合計時間が5.4秒から3.5秒に短縮されます。
00:04:08そのすべてがチェック時間の削減によるものです。4.7秒だったのが2.9秒まで下がりました。
00:04:15今度はTypeScript 6を使って同じコマンドを実行してみましょう。少し時間がかかるので
00:04:20早送りします。しばらく待つと、TypeScript 6は
00:04:2345.3秒で終了しました。全コアで実行したときの3.5秒と比較すると、
00:04:28実質的に私のM3 Maxチップで15倍の向上となります。
00:04:36この3.5秒という数値はここから来ています。もちろんこれを行うと他のプロセスのパフォーマンスを奪いますが、
00:04:43他に何もしていなければ、マシンの全リソースを活用した方が良いでしょう。
00:04:47Goがどうやってこのパフォーマンスを実現しているか理解するため、新コンパイラの実際のコードを見てみましょう。
00:04:52ここにある `bindSourceFiles` 関数は、ファイル内のすべての宣言を構築し、
00:04:57それがどのスコープに属するかを特定する役割を持っています。数千ものファイルを処理する際、
00:05:03各ファイルをループし、バインドする関数をキューに入れて、すべてが完了するのを待ちます。
00:05:09素晴らしいのは、その作業がコア間でどう分散されるかを考慮する必要がない点です。
00:05:14Goのランタイムがすべてを処理してくれます。スレッドの生成やコア間の複雑な通信の管理は不要で、
00:05:20「はい、これ作業ね」と渡すだけで、残りのやり方を自動で判断してくれます。
00:05:26JavaScriptでもほぼ同じコードを書けますが、CPUバウンドな作業では意味がありません。
00:05:32Promiseが並列処理の錯覚を与えたとしても、すべて単一スレッドで順次実行されます。
00:05:38Workerを使えば技術的には回避できますが、オブジェクトの共有はできず、SharedArrayBufferで生のバイト列を送るしかありません。
00:05:43そのため、構文木をWorkerに渡すには全体をシリアライズしてコピーし、反対側で再構築することになります。
00:05:48大きなファイルでは、そのコストが処理自体よりも高くなることがあります。要するに、こうした理由から
00:05:53Goは本質的にCPUバウンドな作業に適しているのです。並列処理を処理できるランタイムがあり、
00:05:58共有メモリがあるためコピーなしでオブジェクトを受け渡せます。
00:06:03コンパイル時間以外で最も体感できるのは、言語サーバーのスピードでしょう。
00:06:07大規模なTypeScriptコードベースで作業したことがある人なら、型のチェックを待つ苦痛を知っているはずです。
00:06:13Intel搭載Macは本当に酷かったのを覚えています。数年前のプロジェクトでは、
00:06:20リポジトリを開いてから赤い波線が表示されるまで最大2分間も待たされ、
00:06:24コードを変更するたびに凄まじい苦痛を味わいました。開発者体験は最悪で、
00:06:29誰もそのコードベースに触りたがりませんでした。しかし新しい言語サーバーなら、IDE上で瞬時にフィードバックが得られます。
00:06:34ファイルを開いて変更を加えれば、文字通り数ミリ秒でエラーが表示されます。
00:06:40たとえ非常に大規模なコードベースを扱っていてもです。パフォーマンスだけでなく、
00:06:46新しい言語サーバーは安定性も向上しました。型チェックが動作しなくなってIDEを再起動する必要性は激減しました。
00:06:51TypeScript 7では、言語サーバーのコマンド失敗が80%以上減少し、
00:06:57サーバーのクラッシュも60%以上減少しました。壁に投げつけられるノートPCが減るのは、
00:07:04環境にとっても実に良いことです。Microsoftが地球環境に配慮していたなんて誰が知っていたでしょうか。
00:07:08また、これがゼロからの再構築ではなく「移植」である点も言及価値があります。
00:07:13TypeScriptチームは細心の注意を払い、新コンパイラが旧バージョンとほぼ完全な互換性を持つようにしました。
00:07:19速度以外で違いに気づくことすらおそらくないでしょう。しかし自分のプロジェクトでTypeScript 7を実行できるようになった一方で、
00:07:24お気に入りのパッケージが対応するのを待つ必要があります。プログラマティックAPIはまだ不足しているため、
00:07:29それに依存しているパッケージは7.1リリースを待つ必要があります。
00:07:35そのため typescript-eslint、ts-jest、ts-node といったパッケージは一時的に遅れをとることになります。
00:07:42現在、TypeScript 7の正式版がダウンロード可能となっていますが、
00:07:47VS Code用のTypeScript 7拡張機能を明示的にインストールする必要があります。
00:07:53デフォルトパッケージはいずれ更新されますが、今はストアで「TypeScript 7」という拡張機能を導入すれば
00:07:58すべて想定通りに動作します。TypeScript 7の機能セットについて詳しく知りたい場合は、
00:08:03まさにそれを解説した動画を撮影しましたので、こちらからご覧いただけます。こうした解説が気に入っていただけたら、
00:08:08ぜひBetter Stackをチャンネル登録してください。何か学びがあれば幸いです。
00:08:12これでTypeScript 7による高速な開発環境を活用できますね。私自身も
00:08:16これを使うのを間違いなく楽しみにしています。ご視聴ありがとうございました。それではまた次回お会いしましょう。