Upgrade to Pro — share decks privately, control downloads, hide ads and more …

TSKaigi Sendai 2026 - tsgo時代のTypeScript Playgro...

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest. →
Avatar for teamLab teamLab PRO
November 01, 2026

TSKaigi Sendai 2026 - tsgo時代のTypeScript Playgroundはどう動くか

このスライドは TSKaigi Sendai 2026の登壇に使用したスライドのアーカイブになります。

チームラボでは、フロントエンドエンジニアを募集しています。
少しでも、チームラボにご興味をお持ち頂けましたら、採用ページをご覧頂けますと幸いです。
https://www.team-lab.com/recruit/

Avatar for teamLab

teamLab PRO

November 01, 2026

More Decks by teamLab

Other Decks in Technology

Transcript

  1. TypeScript Go移植の発表から早1.5年 ネイティブ化で 3x 〜 3.5x 並列化で 3x 〜 3.5x

    https://devblogs.microsoft.com/typescript/typescript-native-port/ © teamLab Inc. 4
  2. ネイティブの利点と代償 起動・実行が速い - CPUが直接実行できるので CPUアーキテクチャに合わせて 最適化できる ソース 代償 - typescript-

    ビルド Apple M系統 typescript- macOS darwin-x64 typescript- OSやCPUごとにバイナリが必要 別環境向けのバイナリは (直接)実行不可 linux-x64 © teamLab Inc. macOS darwin-arm64 Intel系統 Linux Intel・AMD系統 8
  3. WebAssembly(以下WASM) ブラウザなどのJSエンジンが実行できるバイナリ形式 - - 高速で、高効率であり、ポータブルであることを目標にして設計されている - バイナリ形式なのでパースが高速 - OS・CPUに依存しない(同じバイナリがどこでも動く) -

    CPU負荷の高い処理をネイティブに近い速度で実行可能 サンドボックス内で安全に実行される 言語中立(C/C++、Rust、 Go などから生成できる) ソース C++ / Rust / Go ビルド .wasm OS・CPU⾮依存 ブラウザ / ランタイム Chrome / Node.js など JSエンジン サンドボックス内でWASMを実⾏ © teamLab Inc. OS / CPU どの環境でも 14
  4. Go WASMビルド vs TS6 ファイルサイズ サイズ minify後 gzip後 minify +

    gzip後 TS6.0 17.42 MB 11.87 MB 3.36 MB 2.75 MB TS7.0 (Go) 49.55 MB – 10.93 MB – 型チェックの実行時間(Node.js上で実行) basic (2ファイル) Playwright (1,523ファイル) social-app (4,982ファイル) TS6.0 0.41秒 5.2秒 8.8秒 TS7.0 (Go) 0.98秒 (x2.4) 10.0秒 (x1.9) 17.0秒 (x1.9) TS7はビルドした.wasmそのまま、TS6はnpmの言語サービス一式(lib.d.ts・i18nデータ込み)。minifyはJSのみesbuildでminify ビルドターゲットはwasip1(WASI Preview 1)で、Node.jsのWASIで実行 M4 Pro Mac、Node.js 26で計測。実行時間はNode.jsの起動とWASMのコンパイルを含む https://github.com/elecdeer/ts-tinygo © teamLab Inc. 18
  5. WASMサイズの占めるもの TS7.0 (Go) の .wasm(49.5 MB)の内訳 Go依存の部分 21.7 MB(44%) コンパイラ本体のコード

    18.7 MB checker・⾔語サービスなど 標準 ライブラリ 3.9 MB pclntab 13.2 MB 関数名・⾏番号・GC⽤スタックマップ ランタイム 1.4 MB 型情報 3.2 MB lib.d.ts・翻訳 関数名 その他 4.9 MB 1.8 MB 2.5 MB https://github.com/elecdeer/ts-tinygo の bench/wasm-size.mjs で分解 © teamLab Inc. 20
  6. TinyGo 元々はマイコン、組み込みをターゲットに作られたAlternative Goコンパイラ - マイコンのストレージやメモリはkB、多くても数MBレベルなので、 その辺のモチベーションが強い 独自のバックエンドを使っているGoとは違い、LLVMをバックエンドとしている - - LLVMとは

    - 中間言語で表現されるコードを最適化して各種ネイティブコードに変換 するコンパイラの共通基盤 Goのバックエンドよりも効率的にネイティブコードを生成できることが多い © teamLab Inc. 22
  7. TinyGoでTypeScript 7をWASMビルドしてみる TinyGo 0.43とTypeScript 7.0.2で、型チェックを動かすのに必要だったもの - - goroutineを立てずに順番に処理させる( --singleThreaded を常に有効化)

    - TinyGoはgoroutineごとに固定長スタックを確保するので、 ファイルごとにgoroutineを立てるとメモリを使い切るため ビルドオプションでgoroutineのスタックを64KB(デフォルト)から16MBに する - 型チェッカーの深い再帰でヒープメモリがあふれて壊れる © teamLab Inc. 23
  8. Goビルド vs TinyGoビルド サイズ gzip後 TS6.0 17.42 MB 3.36 MB

    0.41秒 TS7.0 (Go) 49.55 MB 10.93 MB 0.98秒 (x2.4) 10.0秒 ( x1.9) 17.0秒 (x1.9) TS7.0 (TinyGo) 20.01 MB 6.12 MB 1.26秒 (x3.1) 30.2秒 (x5.8) 32.2秒 (x3.7) - basic Playwright social-app 5.2秒 8.8秒 Goに比べるとファイルサイズはかなり小さい 一方で速度は更に悪化 © teamLab Inc. 24
  9. 速度面も追ってみる プロファイリングしてみると、GCが遅いっぽい GC:使われなくなったメモリを見つけて回収する処理 Go コンパイラ本体 マップ TinyGo コンパイラ本体 マップ 合計

    17.7秒 合計 31.2秒 6.9秒 7.4秒 アロケーション GC 3.0秒 4.5秒 findHead 3.1秒 WASI呼び出し 11.7秒 その他のGC 5.4秒 GC 17.1秒(全体の55%) その他 TS7.0でsocial-appを型チェックしたときのCPUプロファイル( node --cpu-prof )を、関数の自己時間で処理の種類ごとに集計 © teamLab Inc. 25
  10. GCを減らした結果 初期メモリ2GB: 最初にメモリを多めに確保して、GCを起きにくくする -gc=leaking : GCを切って、全部終わるまで一切解放しない Playwright 実行時間 Playwright ピークメモリ

    social-app 実行時間 social-app ピークメモリ TS6.0 5.2秒 1.20 GB 8.8秒 1.70 GB TS7.0 (Go) 10.0秒 (x1.9) 1.16 GB 17.0秒 (x1.9) 1.77 GB TS7.0 (TinyGo) 30.2秒 (x5.8) 1.83 GB 32.2秒 (x3.7) 3.44 GB TS7.0 (TinyGo, 初期メモリ2GB) 13.3秒 (x2.5) 2.26 GB 24.4秒 (x2.8) 4.29 GB TS7.0 (TinyGo, GCなし) 5.9秒 (x1.1) 3.17 GB メモリ不足 – - GCを減らすほど速くなりTS6にも迫るが、その分メモリを多く使う メモリはNode.js自身を含むピークRSS。social-appはGCなしだとWASMのメモリ上限(4GB)を使い切る © teamLab Inc. 27
  11. あとそもそもJSは速い 主流のJavaScriptエンジンにはJIT(Just In Time)コンパイルの仕組みがある 良く呼ばれる関数は実行中にネイティブコードに部分コンパイルされる 他のスクリプト言語と比較しても十分速いほう JSエンジン JSコード インタプリタ まずバイトコードで実⾏

    V8の例 よく呼ばれる関数 Ignition 最適化コンパイラ 実⾏時の型を前提に機械語へ Maglev / TurboFan ネイティブコード CPUが直接実⾏ 型の前提が崩れたらインタプリタに戻す(脱最適化) © teamLab Inc. 28
  12. TypeScript 7.1 Betaを含めた結果 basic Playwright 実行時間 Playwright ピークメモリ social-app 実行時間

    social-app ピークメモリ TS6.0 0.41秒 5.2秒 1.20 GB 8.8秒 1.70 GB TS7.0 (Go) 0.98秒 (x2.4) 10.0秒 (x1.9) 1.16 GB 17.0秒 (x1.9) 1.77 GB TS7.1 (Go) 0.90秒 (x2.2) 8.1秒 (x1.5) 0.90 GB 13.1秒 (x1.5) 1.32 GB TS7.0 (TinyGo) 1.26秒 (x3.1) 30.2秒 (x5.8) 1.83 GB 32.2秒 (x3.7) 3.44 GB TS7.1 (TinyGo) 0.86秒 (x2.1) 19.0秒 (x3.6) 1.09 GB 18.2秒 (x2.1) 1.92 GB TS7.1 (TinyGo, 初期メモリ2GB) 0.72秒 (x1.8) 6.3秒 (x1.2) 1.83 GB 13.2秒 (x1.5) 2.30 GB TS7.1 (TinyGo, GCなし) 0.55秒 (x1.3) 4.5秒 (x0.9) 1.53 GB 8.1秒 (x0.9) 2.55 GB 7.1 BetaでGoもTinyGoも速くなった、メモリ削減が効いている? TinyGoのGCなしは、大きなプロジェクトならTS6より速い ピークメモリはNode.js自身を含むピークRSS © teamLab Inc. 32
  13. TSCのRust実装が話題 bun checkとかts-rustとかtsrsなどなど - oven-sh/bun - Bun v1.4.3 pingdotgg/ts-rust oxc-project/tsrs

    - Cloudflare: Introducing tsrs: A port of TypeScript to Rust Rustはランタイムをほぼ持たず、GCも無いので WASMバイナリを作る言語として最適 © teamLab Inc. 33
  14. WASMビルドして動かしてみる - bun checkは素直にWASMビルドできなそうだったのでスキップ tsrsはビルド済みWASMがnpmで配布されている basic Playwright 実行時間 Playwright ピークメモリ

    social-app 実行時間 social-app ピークメモリ TS6.0 0.41秒 5.2秒 1.20 GB 8.8秒 1.70 GB TS7.1 (Go) 0.90秒 (x2.2) 8.1秒 (x1.5) 0.90 GB 13.1秒 (x1.5) 1.32 GB TS7.1 (TinyGo, GCなし) 0.55秒 (x1.3) 4.5秒 (x0.9) 1.53 GB 8.1秒 (x0.9) 2.55 GB ts-rust 0.33秒 (x0.8) 2.9秒 (x0.5) 0.57 GB 5.1秒 (x0.6) 0.77 GB tsrs 0.21秒 (x0.5) 1.5秒 (x0.3) 0.37 GB 2.4秒 (x0.3) 0.47 GB 👏 ts-rust・tsrsはTS6より速く、メモリも半分以下 ts-rust・tsrsはそれぞれデフォルトの最適化レベル(ts-rustは opt-level=z 、tsrsは opt-level=s ) ピークメモリはNode.js自身を含むピークRSS © teamLab Inc. 34
  15. GoなのかTinyGoなのか GoなのかTinyGoなのかは分からない - - Jake氏がTinyGoのissueにコメントしているので、TinyGoも検討はしている かも? - https://github.com/tinygo-org/tinygo/issues/4894 - TinyGoビルドだとLSPがシュッと動かなそうだったので、まだちょっと

    難ありかもしれない - 手元で試したところ、7.1だとコンパイル通すのにパッチも必要だった ファイルサイズを取るのか、速度の方を取るのか? © teamLab Inc. 37
  16. TypeScript Playgroundとしては TS 7.1かTS 7.2かは分からないが、そのうち対応されるはず そんなに速度が求められるものでもないので、 公式のPlaygroundは公式のGo or TinyGoビルド になるのでは

    一方、他のブラウザ開発環境ではどうだろう? - StackBlitz (Web Containers)とか tsrsとか使うようになる可能性は全然ありそう - 現状も非公式のWASMビルドパッケージを使っているので - 今後Rust port / forkがどれくらい市民権を得るかによるかも © teamLab Inc. 38
  17. まだまだ伸びしろあります 7.0 → 7.1でかなりパフォーマンスが向上している - GCが多いことがWASMビルドのパフォーマンス低下原因の一つ メモリ消費量が減れば、GCも少なくなり改善が見込める TypeScript Goはまだパフォーマンス改善の余地が残っている(はず!) -

    TSで書かれていたころのTypeScriptはチューニングが大分やり尽くされて いた Go版はまだこれから ファイルサイズもまだ最適化していない数字 - ts-rustのようにlib.*.dtsを圧縮するなど、改善の余地がある © teamLab Inc. 39
  18. まとめ tsgo時代のTypeScript Playgroundはどう動くか → WASMで動く! - TS7.0で現状提供されているネイティブビルドはブラウザでは動かないが、 WASM版を用意すれば動く ただしGoのWASMビルドは、現状TS6(JS)より遅くてサイズも大きい TinyGoならサイズは小さくなるが、GCがネックで速度はさらに落ちる

    - GCを減らしたり、TS7.1 Betaの改善でかなり速くなる Rust移植版のWASMビルドは、TS6より速くメモリも少ない 公式のWASMビルドは7.1のロードマップに載っていて、 Playgroundもそのうち対応されるはず © teamLab Inc. 40