AOT(Ahead Of Time) 称为 运行前编译,指的是在程序运行之前,已经编译成对应平台的机器码,不需要在运行中解释编译,就可以直接运行。常见例子有 C 和 C++。
虽然,我们会区别 JIT 和 AOT 两种编译模式,但实际上,有很多语言并不是完全使用 JIT 或者 AOT 的,通常它们会混用这两种模式,来达到最大的性能优化。
Dart 支持的编译模式
Dart VM 支持四种编译模式:
- Script:最常见的 JIT 模式,可以直接在虚拟机中执行 Dart 源码,像解释型语言一样使用。
通过执行 dart xxx.dart
就可以运行,写一些临时脚本,非常方便。
- Kernel Snapshots:JIT 模式,和 Script 模式不同的是,这种模式执行的是 Kernel AST 的二进制数据,这里不包含解析后的类和函数,编译后的代码,所以它们可以在不同的平台之间移植。
在 Flutter’s Compilation Patterns 这篇文章中,将 Kernel Snapshots 称为 Script Snapshots 也是对的,这应该是之前的叫法,从 dart-lang 的 wiki 中可以看出来:
Dart Kernel 是 Dart 程序中的一种中间语言,更多的资料可阅读 Kernel Documentation。
通过执行 dart --snapshot-kind=kernel --snapshot=xx.snapshot xx.dart
生成。
- JIT Application Snapshots:JIT 模式,这里执行的是已经解析过的类和函数,所以它会运行起来会更快。但是这不是平台无关,它只能针对 32位 或者 64位 架构运行。
通过执行 dart --snapshot-kind=app-jit --snapshot=xx.snapshot xx.dart
生成。
- AOT Application Snapshots:AOT 模式,在这种模式下,Dart 源码会被提前编译成特定平台的二进制文件。
要使用 AOT 模式,需要使用 dart2aot
命令, 具体使用为:dart2aot xx.dart xx.dart.aot
,然后使用 dartaotruntime
命令执行。
Dart JIT 模式需要配合 Dart VM(虚拟机) ,AOT 则会使用 runtime 来执行,引用官网中的图片来说明:
可以用下面这张图来总结上面的四种模式:
四种模式下的产物大小和启动速度比较:
Flutter 构建过程
下面的分析都是基于 v1.5.4-hotfix.2
执行 flutter build apk
时,默认会生成 release APK,实际是执行的 sdk/bin/flutter 命令,参数为 build apk:
DART_SDK_PATH=“ F L U T T E R R O O T / b i n / c a c h e / d a r t − s d k " D A R T = " FLUTTER_ROOT/bin/cache/dart-sdk" DART=" FLUTTERROOT/