TypeScript 7が正式リリース、驚異的なスピードを実現

BBetter Stack
컴퓨터/소프트웨어AI/미래기술

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これを使うのを間違いなく楽しみにしています。ご視聴ありがとうございました。それではまた次回お会いしましょう。

Key Takeaway

TypeScript 7はコンパイラをGo言語で再構築し共有メモリによるマルチコア並列処理を実現したことで、VS Codeのビルド速度を125秒から10秒へと大幅に短縮した。

Highlights

  • TypeScript 7ではコンパイラがGo言語へ移植され、VS Codeのコードベース(約8000ファイル、130万行)のビルド時間が旧バージョンの125秒から10秒へ短縮された。

  • コンパイル高速化の要因は、ネイティブコード化による向上と共有メモリを用いたマルチコア並列処理が約半々を占める。

  • Apple M3 Max(14コア)環境でチェッカー数を12に設定した場合、VS Codeの診断処理時間が45.3秒から3.5秒へ短縮され、約15倍のパフォーマンス向上を記録する。

  • 新言語サーバーの導入により、型チェックのエラー表示フィードバックが数ミリ秒単位まで高速化し、コマンド失敗率は80%以上、クラッシュ率は60%以上減少した。

  • typescript-eslintやts-jestなどの主要ツールが依存するプログラmatic APIの完全移植はTypeScript 7.1での提供予定となっている。

Timeline

TypeScript 7リリースとビルド性能の大幅向上

  • Goコンパイラを搭載したTypeScript 7が正式リリースされた。
  • VS Codeの130万行のコードベースにおけるビルド時間が125秒から10秒へ短縮された。

1年以上の開発期間を経て、Go言語へ移植されたTypeScript 7がnpmで配信開始となった。旧コンパイラと比較して巨大なプロジェクトのコンパイル時間が10分の1以下へ縮小し、開発速度に根本的な変化をもたらす。

JavaScriptの構造的限界とGo言語選定の理由

  • Single-threadedなJavaScriptは抽象構文木の処理や型チェックなどのCPU密集型タスクでボトルネックになる。
  • Goはネイティブコード実行と共有メモリによる並列処理によってCPUの全コアを活用する。

JavaScriptはブラウザやUI向けに最適化されており、計算集中型処理では単一コアのパフォーマンス限界に達する。Workerで処理を分散する場合もデータのシリアライズとデシリアライズのオーバーヘッドが発生する。Go言語を採用することで、共有メモリを用いた複数スレッドの同時実行が可能となり、ネイティブ実行と並列処理が高速化を実現した。

主要プロジェクトにおけるベンチマーク結果とマルチコア最適化

  • Blueskyのコンパイル時間は24.3秒から2.8秒へ、Playwrightは12.8秒から1.5秒へ短縮された。
  • 型チェッカーの並列数を指定するフラグにより、M3 Max環境で処理時間を3.5秒まで削減できる。

CPUの単体コア性能が飽和する一方でコア数が増加している現代のハードウェア環境において、Go言語への移植は全コアの計算資源解放を可能にした。型チェック処理を分割して同時実行するフラグ(`checkers 12`)を指定すると、VS Codeの診断処理は旧バージョンの45.3秒から3.5秒まで加速し、15倍の性能差が生じる。

Goランタイムによる並列処理制御の内部メカニズム

  • ファイル内の宣言構築を行う `bindSourceFiles` 関数などのタスク分散はGoランタイムが自動管理する。
  • 共有メモリの存在により構文木などのオブジェクトをコピーなしでスレッド間に受け渡せる。

Goコンパイラ内部では、ファイルのバインド作業をキューに投入するだけで、ランタイムがスレッド生成やコア間通信を最適化する。JavaScriptのようにPromiseによる擬似並列処理を行ったり、Worker間で重いシリアライズ処理を伴う `SharedArrayBuffer` やデータコピーを行ったりする必要がなく、CPUバウンドな処理が本質的に高効率化される。

言語サーバーの安定性向上と既存エコシステムへの影響

  • 言語サーバーのエラーフィードバックが数ミリ秒に短縮され、コマンド失敗率は80%以上削減された。
  • プログラマティックAPIの完全対応はバージョン7.1を予定しており、関連パッケージの対応に一部タイムラグが生じる。

新言語サーバーの導入により、大規模コードベースにおける型チェックの遅延が解消され、クラッシュ率が60%以上低下した。旧バージョンとの高い互換性が保持されている一方、プログラマティックAPIに依存するtypescript-eslintやts-jestなどの周辺ツールはTypeScript 7.1のリリースを待つ必要がある。VS Codeで利用するには専用の拡張機能の明示的なインストールが必要となる。

Community Posts

View all posts