Closed9

WebAssembly compilation pipelineを読む

UMASHIBAUMASHIBA

wasmもより良いパフォーマンスを出すためにv8の内部でいくつかのコンパイラでコンパイルしているらしい。

UMASHIBAUMASHIBA

Liftoff

  • Liftoffはwasmのベースラインコンパイラ
  • Liftoffはone-pass compiler(中間表現を作らず一気にマシンコードまでコンパイルするコンパイラのことっぽい)
  • Liftoffは高速なコード生成に優れているけど、小さい最適化しかできない
  • 10数MB/sでコンパイルできる
  • 一回Liftoffのコンパイルが終わったらそのコンパイルされたwasm moduleはJSへ返される
UMASHIBAUMASHIBA

Turbofan

  • Liftoffは短い時間で結構早いマシンコードを生成する。けれどそれはwasmの各命令ごとにコンパイルしているから最適化の余地がほとんど残されていない。
  • Liftoffのコンパイルが終わった後、v8は即座に全ての関数をTurbofanによって再コンパイルしてモジュールを"tier up"(結びつける的な意味っぽい)する
  • Turbofanはmulti-pass compilerであり、中間表現を挟むことでより高度な最適化を可能にしている。
  • Turbofanはwasmを関数ごとに最適化しており、Turbofanでのその関数のコンパイルが終わり次第Liftoffでコンパイルされたその関数の機械語と置き換えられる
  • ただしTurbofanで生成された関数の機械語に置き換えられるといってもon-stack-replacementは行われない(on-stack-replacementはすでに呼ばれていて実行中のLiftoffによって生成された関数の置き換えは行わないみたいなニュアンスっぽい)
UMASHIBAUMASHIBA

Code caching

WebAssembly moduleをWebAssembly.compileStreamingを使ってコンパイルするとTurbofanが生成したマシンコードはキャッシュされる。そして次回同じURLにアクセスすると新しくコンパイルはされず、以前キャッシュしたモジュールが読み込まれる。
詳しくはCode caching for WebAssembly developers

UMASHIBAUMASHIBA

Debugging

Turbofanは最適化の過程でコードの順番を変えたり、スキップしたり変数を削除したりする。

ブレークポイントを設定しようとしてもどこで止めれば良いかわからなかったりしてデバッグに適していない

DevToolsでのデバッグでは全てのTurbofanコードはLiftoffコードに置きえられる(tiered offという)

そのためDevtoolsでのデバッグはうまくいくようになっている

UMASHIBAUMASHIBA

Profiling

パフォーマンスタブを開いて"Record"ボタンを押した場合はもう一度Turbofanによるコンパイルがもう一度行われる。

パフォーマンスタブで計測される場合、
LiftoffのコードはTurbofanのコンパイルが完了するまでしか使われず、多くの時間実行されるTurbofanよりもだいぶ遅いのでプロファイリングの際の代表的な値にはならない。

UMASHIBAUMASHIBA

flags for experimentation

v8やchromeではexprimentalなflagを使ってLiftoffのみのコンパイル、Turbofanのみのコンパイルを指定することができる、またLazy compileも同様に可能。以下のフラグはそのためのもの

  • Liftoff only
    • V8では: --liftoff --no-wasm-tier-up flag
    • Chromeでは: WebAssembly tiering(chrome://flags/#enable-webassembly-tiering)を無効にし、WebAssembly baseline compiler(chrome://flags/#enable-webassembly-baseline)を有効にする
  • Turbofan only
    • V8では: --no-liftoff --no-wasm-tier-up
    • Chromeでは: WebAssembly tiering(chrome://flags/#enable-webassembly-tiering)を無効にし、WebAssembly baseline compiler(chrome://flags/#enable-webassembly-baseline)も無効にする
  • Lazy compilation(最初に全てコンパイルするのではなく関数が初めて呼び出された時にコンパイルすること)
    • V8では: --wasm-lazy-compilation
    • Chromeでは: WebAssembly lazy compilation (chrome://flags/#enable-webassembly-lazy-compilation)を有効化
UMASHIBAUMASHIBA

Compile time

コンパイル時間を測定方法について

  • Liftoff
    • v8のプロダクション構成ではjsから以下の二つのうちのどちらかを計測することで測定できる
      • 新しいWebAssembly.Module()が終了するまでの時間
      • WebAssembly.compile()がpromiseを解決するまでの時間
  • Turbofan
    • chrome://tracing/でv8.wasmカテゴリを有効にして計測する
このスクラップは2021/06/17にクローズされました