はじめに
FlutterのDartコードはDart VM (バーチャルマシーン) 上で動作していますが、デバッグモードとリリースモードの違いや仕組みについて簡単に解説します。
動作モード
動作モードにはデバッグモード (JIT) とリリースモード (AOT) の2種類が存在します。
デバッグモード (JIT)
Flutterにおける通常のデバッグ時に利用するモードです。このモードでは、便利なホットリロード機能が利用できます。
JITとはJust In Time
の略称で、実行時コンパイラと呼ばれるものです。クラスやメソッドなどの単位でコードが実行される時にコンパイルして実行するインタプリタな方式です。OSやCPUなどのプラットフォームに依存せずにコードを実行できるメリットがある一方で、速度的には遅くなってしまいます。
この速度が遅い欠点を改善するために、適応的コンパイル (Adaptive Compilation) という仕組みが導入されるのが一般的です。最初はインタプリタで実行時にコンパイルをするものの、頻繁にコールされるようなコードを最適化しながらコンパイルすることで、実行プログラムや環境に最適化する仕組みです。これにより初期はスピードが遅いものの、実行する時間が長くなるにつれ、パフォーマンスが上がっていく傾向があります。
このモード時においてFlutterは、Dartコード (バイトコード) を一つのバイナリデータ (flutter_assets/kernel_blob.bin) として固めて、Flutter Engine初期化時にDart VMにロードします。
リリースモード (AOT)
Flutterにおけるリリース時のモードです。このモードでは、ホットリロード機能が使えません。
AOTとはAhead-Of-Time
の略称で、事前コンパイラと呼ばれるものです。C++のように実行前にコンパイラでビルドしてターゲットのOS/CPU向けの実行バイナリを作っておく方式です。
実行時にコンパイルの必要がないため、一般的にはJITよりも数倍のパフォーマンスが出せますが、プログラムの内容次第では以下のように実行につれて最適化が進み、逆にJITの方がパフォーマンスが高くことがあります。
スナップショット
AOT時、Dart VM自体が高速起動できる仕組みを保有しています。それがスナップショット機能で、Dart VMおよびRoot Isolateの起動高速化を実現しています。
ノリとしては同じ処理を毎回行うのは無駄なので、起動処理完了後の状態やコアライブラリをバイナリファイルとして保有しておき、Dart VM起動時にロードしちゃおう!そうしたら高速起動実現出来るじゃん!というパターンです。LinuxなどのOSでも良くあるスナップショットブートと同じようなイメージです。