flutter 学习
# flutter 学习
# Flutter的编译模式
# 解释与编译
解释(Interpreter):解释就是把源程序以句为单位,每句每句的解释并执行;如果语句出现在循环体当中,比如循环10次,该语句就要被解释执行10次;解释执行过程不产生目标代码。很多脚本语言都是解释执行的。
编译(Compilation):编译是把源代码一次性翻译成目标代码,目标代码可能是可直接运行的机器语言,或是已存在相应翻译器的不可执行语言。比如C/C++就是典型的编译之后才能执行的高级编程语言,这种编译也被称为静态编译(Static Compilation)。编译有时还指将高级语言编译成一种中间形态的字节码,比如java语言,这种中间形态的字节码比如要在JVM里面才能被执行。
# JIT
JIT全称 Just In Time(即时编译),典型的例子就是 v8,它可以即时编译并运行 JavaScript。所以你只需要输入源代码字符串,v8就可以帮你编译并运行代码。通常来说,支持 JIT的语言一般能够支持自省函数(eval),在运行时动态地执行代码。 JIT模式的优势是显而易见的,可以动态下发和执行代码,而不用管用户的机器是什么架构,为应用的用户提供丰富而动态地内容。 但 JIT的劣势也是显而易见的,大量字符串的代码很容易让 JIT编译器花费很多时间和内存进行编译,给用户带来的直接感受就是应用启动慢。
JIT的意思是说,首先仍然是compilation,但有caching,不用象解释那样把循环体里面出现的代码重复解释;同时有目标机器代码。这是相对于interpretation的好处。另外相对于静态编译的好处是,在编译过程对代码进行优化。选择性的编译某个函数或任意某段代码。JIT具体的做法是这样的:当函数第一被调用时,JIT将该函数编译成机器语言;当再次遇到该函数时则直接从cache中执行已编译好的机器语言。
# AOT
AOT全称 Ahead Of Time(事前编译),典型的例子就是 C/C++,LLVM或 GCC通过编译并生成 C/C++的二进制代码,然后这些二进制通过用户安装并取得执行权限后才可以通过进程加载执行。 AOT的优势也是显而易见的,事先编译好的二进制代码,加载和执行的速度都会非常快。(所以编程语言速度排行榜上前列都是 AOT编译类语言)这样的速度可以在密集计算场景下给用户带来非常好的体验,比如大型游戏的引擎渲染和逻辑执行。
但是 AOT的劣势也是显而易见的,编译需要区分用户机器的架构,生成不同架构的二进制代码,除了架构,二进制代码本身也会让用户下载的安装包比较大。二进制代码一般需要取得执行权限才可以执行,所以无法在权限比较严格的系统中进行动态更新(如 iOS)
# Dart 的编译模式
- Script:最普通的 JIT模式,在 PC命令行调用 dart vm执行 dart源代码文件即是这种模式。
- JIT模式,和上一个不同的是,这里载入的是已经 token化的 dart源代码,提前执行了上一步的 lexer步骤。
- JIT模式,这种模式来源于 dart vm直接载入源码后 dump出数据。dart vm通过这种数据启动会更快。不过值得一提的是这种模式是区分架构的,在 x64上生成的数据不可以给 arm使用。
- AOT模式,直接将 dart源码编译出 .S文件,然后通过汇编器生成对应架构的代码。
# Flutter的编译模式
- Script:同 Dart Script模式一致,虽然 Flutter支持,但暂未看到使用,毕竟影响启动速度
- Script Snapshot:同 Dart Script Snapshot一致,同样支持但未使用,Flutter有大量的视图渲染逻辑,纯 JIT模式影响执行速度。
- Kernel Snapshot:Dart的 bytecode 模式,与 Application Snapshot不同,bytecode模式是不区分架构的。 Kernel Snapshot在 Flutter项目内也叫 Core Snapshot。bytecode模式可以归类为 AOT编译。
- Core JIT:Dart的一种二进制模式,将指令代码和 heap数据打包成文件,然后在 vm和 isolate启动时载入,直接标记内存可执行,可以说这是一种 AOT模式。Core JIT也被叫做 AOTBlob
- AOT Assembly: 即 Dart的 AOT模式。直接生成汇编源代码文件,由各平台自行汇编。
# 开发阶段的编译模式
在开发阶段,我们需要 Flutter的 Hot Reload和 Hot Restart功能,方便 UI快速成型。同时,框架层也需要比较高的性能来进行视图渲染展现。因此开发模式下,Flutter使用了 Kernel Snapshot模式编译。 在打包产物中,你将发现几样东西:
- isolate_snapshot_data:用于加速 isolate启动,业务无关代码,固定,仅和 flutter engine版本有关
- platform.dill:和 dart vm相关的 kernel代码,仅和 dart版本以及 engine编译版本有关。固定,业务无关代码。
- vm_snapshot_data: 用于加速 dart vm启动的产物,业务无关代码,仅和 flutter engine版本有关
- kernel_blob.bin:业务代码产物
# 关于Dart
为什么 Flutter 会选择 Dart ? flutter 是从 web 演化过来的框架,为什么不使用 JS 而是使用 Dart?可能出于性能考虑。 flutter团队中大部分成员都具有 Web (Chromium) 背景。 在最初设计上,他们也曾反复考虑 Web 技术,而在语言选型上也考虑过 JavaScript。应该不会有人比他们更了解 JavaScript 与 Web 了吧,但你看看这些开发过 Chromium 的人最后还是放弃了 JavaScript,我们有理由相信他们是经过深思熟虑后做出的决定。按照 Google 工程师的话来说就是「我们关注包括 Web 技术在内的很多技术,我们取其精华并勇敢地扔掉历史包袱。」