Dart JIT 与 AOT

简单聊聊 Dart 的 JIT 和 AOT 模式。

Dart 官方有如下介绍:

Dart Native includes both a Dart VM with JIT (just-in-time) compilation and an AOT (ahead-of-time) compiler for producing machine code

-w725

Dart Native enables running Dart code compiled to native ARM or X64 machine code for mobile, desktop, and server apps.

简单来说,Dart Native 同时支持 JIT 和 AOT。Dart 这种设计好处如下:

  • Dart VM JIT 便于轻量快速开发,它既支持纯解释执行,也可对代码进行运行时优化
  • Dart AOT 编译器将代码编译成原生的 ARM 或 X64 代码,提升发布的代码运行效率

命令行工具

Dart SDK 分别为 JIT 和 AOT 提供不同的工具。

dart VM tool

dart | Dart

You can use the dart tool (bin/dart) to run Dart command-line apps such as server-side scripts, programs, and servers.

dart 命令支持如下的常用选项:

  • --enable-asserts - 开启断言
  • --version - 查看 Dart VM 版本

另外它还支持 Observatory 选项,用于分析和调试 Dart 程序。常用选项包括:

  • --enable-vm-service - 在本地 8181 端口开启 Observatory 服务
  • --observe - 相当于同时指定 --enable-vm-service--pause-isolates-on-exit

-w794

(小技巧:如果你是使用的是 iTerm,按住 Command 键后将光标放在)

关于 Observatory 的更多用法见 Observatory

dart2native

Releases before Dart 2.6 contained a tool named dart2aot that produced AOT snapshots. The dart2native command replaces dart2aot and has a superset of the dart2aot functionality.

Dart 2.6 is now available, with support for compiling to self-contained, native executables.

Dart 语言本身还在快速演化中。所以要注意以下变化:

  • 在 Dart 2.6 以及之前版本,dart2aot 用于生成 AOT 镜像
  • Dart 2.6 之后,dart2native 命令取代了 dart2aot (前者是后者的超集)。

Dart 2.6 近期刚刚发布,这个版本开始才支持将 Dart 代码编译成自包含、独立的原生可执行程序。(当然,这只是形式上的改进,并不是 Dart 中的新技术,因为相关技术很早用于 Flutter 平台了)。

使用 dart2native 命令将对 Dart 程序进行 AOT (ahead-of-time) 编译,生成原生 ARM 或 X64 机器码。

dart2native 命令的产物分成两种。一种是 独立的可执行程序 (缺省是这种),它是原生的机器码,由 Dart 代码及其依赖编译而来,再加上一个很小用于类型检查和垃圾回收的 Dart 运行时。

dart2native 命令用法如下:

1
2
3
dart2native bin/main.dart -o bin/my_app
cp bin/my_app .
./my_app

另一种是 AOT snapshot,它不包含 Dart 运行时,所以需要使用 dartaotruntime 来运行。

dartaotruntime

dartaotruntime 命令用法如下:

1
2
dart2native bin/main.dart -k aot
dartaotruntime bin/main.aot

Flutter 采用 AOT snapshot 这种形式。讲 Flutter 架构时会看到这张图,

图中 Flutter Engine 层中的 Dart 即 Dart 运行时,也正是这里提到的 dartaotruntime

不过 Flutter 自带的 Dart SDK 中似乎找不到 dart2aotdart2native 命令,以下两个 issue 提到了这个问题。

Announcing Dart 2.6 with dart2native: Compile Dart to self-contained, native executables 对 Flutter 中不包含 dart2aotdart2native 有如下解释:

If you’re getting the Dart SDK via Flutter, note that current Flutter builds have incomplete dart2native support. Until Dart 2.6 reaches Flutter stable, we recommend you install the Dart 2.6 SDK from dart.dev/get-dart.

可以从 Dart 官网 下载安装 Dart SDK,它包含 dart2native 命令。

Dart SDK 中的 dart2native 命令

性能测试

写一个简单的 Dart 程序分别测试下 JIT 和 AOT 模式的性能。

1
2
3
4
5
6
7
// demo.dart
main(List<String> args) {
double area;
for (int i = 0; i < 50000000; i++) {
area = i * 3.14 * 3.14;
}
}

-w779

从测试数据可以看到,AOT 下的执行效率确实比 JIT 高多了。

Update: 2019-11-23 16:48

这篇文章 中 “Dart is as slow as Python” 这一节提到了 Dart 的性能问题,这里可以找到很多参考数据

参考