`
猫耳呀
  • 浏览: 167305 次
社区版块
存档分类
最新评论

深入理解flutter的编译原理与优化

 
阅读更多

摘要: 闲鱼技术-正物 问题背景 对于开发者而言,什么是Flutter?它是用什么语言编写的,包含哪几部分,是如何被编译,运行到设备上的呢?Flutter如何做到Debug模式Hot Reload快速生效变更,Release模式原生体验的呢?Flutter工程和我们的Android/iOS工程有何差别,关...

闲鱼技术-正物

问题背景

对于开发者而言,什么是Flutter?它是用什么语言编写的,包含哪几部分,是如何被编译,运行到设备上的呢?Flutter如何做到Debug模式Hot Reload快速生效变更,Release模式原生体验的呢?Flutter工程和我们的Android/iOS工程有何差别,关系如何,又是如何嵌入Android/iOS的呢?Flutter的渲染和事件传递机制如何工作?Flutter支持热更新吗?Flutter官方并未提供iOS下的armv7支持,确实如此吗?在使用Flutter的时候,如果发现了engine的bug,如何去修改和生效?构建缓慢或出错又如何去定位,修改和生效呢?

凡此种种,都需要对Flutter从设计,开发构建,到最终运行有一个全局视角的观察。

本文将以一个简单的hello_flutter为例,介绍下Flutter相关原理及定制与优化。

Flutter简介

图片描述

Flutter的架构主要分成三层:Framework,Engine和Embedder。

Framework使用dart实现,包括Material Design风格的Widget,Cupertino(针对iOS)风格的Widgets,文本/图片/按钮等基础Widgets,渲染,动画,手势等。此部分的核心代码是:flutter仓库下的flutter package,以及sky_engine仓库下的io,async,ui(dart:ui库提供了Flutter框架和引擎之间的接口)等package。

Engine使用C++实现,主要包括:Skia,Dart和Text。Skia是开源的二维图形库,提供了适用于多种软硬件平台的通用API。其已作为Google Chrome,Chrome OS,Android, Mozilla Firefox, Firefox OS等其他众多产品的图形引擎,支持平台还包括Windows7+,macOS 10.10.5+,iOS8+,Android4.1+,Ubuntu14.04+等。Dart部分主要包括:Dart Runtime,Garbage Collection(GC),如果是Debug模式的话,还包括JIT(Just In Time)支持。Release和Profile模式下,是AOT(Ahead Of Time)编译成了原生的arm代码,并不存在JIT部分。Text即文本渲染,其渲染层次如下:衍生自minikin的libtxt库(用于字体选择,分隔行)。HartBuzz用于字形选择和成型。Skia作为渲染/GPU后端,在Android和Fuchsia上使用FreeType渲染,在iOS上使用CoreGraphics来渲染字体。

Embedder是一个嵌入层,即把Flutter嵌入到各个平台上去,这里做的主要工作包括渲染Surface设置,线程设置,以及插件等。从这里可以看出,Flutter的平台相关层很低,平台(如iOS)只是提供一个画布,剩余的所有渲染相关的逻辑都在Flutter内部,这就使得它具有了很好的跨端一致性。

Flutter工程结构
本文使用开发环境为flutter beta v0.3.1,对应的engine commit:09d05a389。

以hello_flutter工程为例,Flutter工程结构如下所示:

图片描述

其中ios为iOS部分代码,使用CocoaPods管理依赖,android为Android部分代码,使用Gradle管理依赖,lib为dart代码,使用pub管理依赖。类似iOS中Cocoapods对应的Podfile和Podfile.lock,pub下则是pubspec.yaml和pubspec.lock。

Flutter模式

对于Flutter,它支持常见的debug,release,profile等模式,但它又有其不一样。

Debug模式:对应了Dart的JIT模式,又称检查模式或者慢速模式。支持设备,模拟器(iOS/Android),此模式下打开了断言,包括所有的调试信息,服务扩展和Observatory等调试辅助。此模式为快速开发和运行做了优化,但并未对执行速度,包大小和部署做优化。Debug模式下,编译使用JIT技术,支持广受欢迎的亚秒级有状态的hot reload。

Release模式:对应了Dart的AOT模式,此模式目标即为部署到终端用户。只支持真机,不包括模拟器。关闭了所有断言,尽可能多地去掉了调试信息,关闭了所有调试工具。为快速启动,快速执行,包大小做了优化。禁止了所有调试辅助手段,服务扩展。

Profile模式:类似Release模式,只是多了对于Profile模式的服务扩展的支持,支持跟踪,以及最小化使用跟踪信息需要的依赖,例如,observatory可以连接上进程。Profile并不支持模拟器的原因在于,模拟器上的诊断并不代表真实的性能。

鉴于Profile同Release在编译原理等上无差异,本文只讨论Debug和Release模式。

事实上flutter下的iOS/Android工程本质上依然是一个标准的iOS/Android的工程,flutter只是通过在BuildPhase中添加shell来生成和嵌入App.framework和Flutter.framework(iOS),通过gradle来添加flutter.jar和vm/isolate_snapshot_data/instr(Android)来将Flutter相关代码编译和嵌入原生App而已。因此本文主要讨论因flutter引入的构建,运行等原理。编译target虽然包括arm,x64,x86,arm64,但因原理类似,本文只讨论arm相关(如无特殊说明,android默认为armv7)。

Flutter代码的编译与运行(iOS)
Release模式下的编译
release模式下,flutter下iOS工程中dart代码构建链路如下所示:

图片描述

其中gen_snapshot是dart编译器,采用了tree shaking(类似依赖树逻辑,可生成最小包,也因而在Flutter中禁止了dart支持的反射特性)等技术,用于生成汇编形式的机器代码,再通过xcrun等编译工具链生成最终的App.framework。换句话说,所有的dart代码,包括业务代码,三方package代码,它们所依赖的flutter框架代码,最终将会变成App.framework。

tree shaking功能位于gen_snapshot中,对应逻辑参见: engine/src/third_party/dart/runtime/vm/compiler/aot/precompiler.cc

dart代码最终对应到App.framework中的符号如下所示:

图片描述

事实上,类似Android Release下的产物(见下文),App.framework也包含了kDartVmSnapshotData,kDartVmSnapshotInstructions,kDartIsolateSnapshotData,kDartIsolateSnapshotInstructions四个部分。为什么iOS使用App.framework这种方式,而不是Android的四个文件的方式呢?原因在于在iOS下,因为系统的限制,Flutter引擎不能够在运行时将某内存页标记为可执行,而Android是可以的。

Flutter.framework对应了Flutter架构中的engine部分,以及Embedder。实际中Flutter.framework位于flutter仓库的/bin/cache/artifacts/engine/ios*下,默认从google仓库拉取。当需要自定义修改的时候,可通过下载engine源码,利用Ninja构建系统来生成。

Flutter相关代码的最终产物是:App.framework(dart代码生成)和Flutter.framework(引擎)。从Xcode工程的视角看,Generated.xcconfig描述了Flutter相关环境的配置信息,然后Runner工程设置中的Build Phases新增的xcode_backend.sh实现了Flutter.framework的拷贝(从Flutter仓库的引擎到Runner工程根目录下的Flutter目录)与嵌入和App.framework的编译与嵌入。最终生成的Runner.app中Flutter相关内容如下所示:

图片描述

其中flutter_assets是相关的资源,代码则是位于Frameworks下的App.framework和Flutter.framework。

Debug模式下的编译
Debug模式下flutter的编译,结构类似Release模式,差异主要表现为两点:

1.Flutter.framework

因为是Debug,此模式下Framework中是有JIT支持的,而在Release模式下并没有JIT部分。

2.App.framework

不同于AOT模式下的App.framework是Dart代码对应的本地机器代码,JIT模式下,App.framework只有几个简单的API,其Dart代码存在于snapshot_blob.bin文件里。这部分的snapshot是脚本快照,里面是简单的标记化的源代码。所有的注释,空白字符都被移除,常量也被规范化,也没有机器码,tree shaking或者是混淆。

App.framework中的符号表如下所示:

图片描述

对Runner.app/flutter_assets/snapshot_blob.bin执行strings命令可以看到如下内容:

图片描述

Debug模式下main入口的调用堆栈如下:

debug isolate main callstack

Flutter代码的编译与运行(Android)
鉴于Android和iOS除了部分平台相关的特性外,其他逻辑如Release对应AOT,Debug对应JIT等均类似,此处只涉及两者不同。

Release模式下的编译
release模式下,flutter下Android工程中dart代码整个构建链路如下所示:

图片描述

其中vm/isolate_snapshot_data/instr内容均为arm指令,将会在运行时被engine载入,并标记vm/isolate_snapshot_instr为可执行。vm_中涉及runtime等服务(如gc),用于初始化DartVM,调用入口见Dart_Initialize(dart_api.h)。isolate__则是对应了我们的App代码,用于创建一个新的isolate,调用入口见Dart_CreateIsolate(dart_api.h)。flutter.jar类似iOS的Flutter.framework,包括了engine部分的代码(Flutter.jar中的libflutter.so),以及一套将Flutter嵌入Android的类和接口(FlutterMain,FlutterView,FlutterNativeView等)。实际中flutter.jar位于flutter仓库的/bin/cache/artifacts/engine/android*下,默认从google仓库拉取。当需要自定义修改的时候,可通过下载engine源码,利用Ninja构建系统来生成flutter.jar。

原文链接

分享到:
评论

相关推荐

    Flutter完整开发实战详解系列.pdf

    最后,作者会分享一些对Flutter技术未来的看法和展望,帮助开发者了解Flutter的发展趋势。 上述内容构成了Flutter完整开发实战详解系列的框架,涵盖了从入门到深入的各个阶段,为开发者提供了全面的Flutter学习路径...

    Flutter完整开发实战详解 PDF

    12. 全面深入理解状态管理设计:讨论更多状态管理方案,如Provider、Riverpod等。 13. 全面深入触摸和滑动原理:探讨手势识别和滑动事件的处理机制。 十四、混合开发打包Android篇:可能涉及如何将Flutter模块嵌入...

    Flutter 完整开发实战详解系列

    最后,我们还将提供一些关于Flutter面试的常见知识点总结,以及对未来Flutter发展方向的展望,帮助读者更好地准备面试或了解Flutter的未来趋势。 以上就是从Flutter开发实战系列文章中的标题、描述和部分内容中提取...

    flutter跨平台

    通过实际的小项目,例如构建一个简单的待办事项应用,来深入理解Flutter的架构和工作原理。这包括数据持久化、状态管理(如Provider或Riverpod)以及网络请求的处理。 九、优化与性能提升 Flutter应用的性能优化...

    逆向Flutter应用的复杂性.pdf

    例如,在解决GreHack CTF 2023 Dart挑战时,就需要深入理解AOT快照的特点,并结合具体的挑战要求来设计合理的解决方案。 #### 七、结论 逆向Flutter应用尤其是针对Android恶意软件的逆向分析是一项极具挑战性的任务...

    flutter逆向工具集

    总的来说,Flutter逆向工具集旨在帮助开发者深入理解Flutter应用的工作原理,进行故障排查、安全审计或定制化开发。然而,这些技术应谨慎使用,遵守软件许可协议,并且在合法和道德范围内操作。

    flutter開發基本文件以及教程

    以上只是Flutter开发基础知识的一部分,随着对框架的深入学习,开发者会接触到更多高级主题,如插件开发、异步处理、性能优化等。这个压缩包文件很可能是为了引导新手逐步进入Flutter开发世界,通过实践和教程帮助...

    Flutter跨平台开发.rar

    通过深入理解和实践,开发者可以充分利用Flutter的优势,创造出富有创新和吸引力的应用程序。这份资料将是你探索Flutter世界的重要指南,无论你是初学者还是经验丰富的开发者,都能从中获益匪浅。

    FlipperSDKforFlutter可帮助您调试在模拟器或连接的物理开发设备中运行的Flutter应用

    文件 `flutter_flipperkit-master` 很可能包含了 Flutter FlipperKit 的源码,这将允许开发者深入理解其工作原理,甚至可以根据需要对其进行自定义或扩展。对于想要深入研究或定制 Flipper 功能的开发者来说,这是一...

    flutter_counter:Flutter中的计数器应用程序

    【Flutter中的计数器应用程序——深入理解Flutter框架与C++基础】 Flutter是Google推出的一款用于构建高性能、跨平台的移动应用程序的开源UI工具包。它允许开发者使用单一代码库为iOS和Android创建美观且响应迅速的...

    Flutter 汉字手写识别源码,基于Dart 语言, 识别率 100%

    首先,我们要了解Flutter的工作原理。Flutter是基于Dart语言的,Dart是一种现代的、面向对象的、类型安全的语言,具有高效的编译和运行时性能。Flutter的UI框架采用了Widget为基础的设计,使得开发者可以通过组合可...

    web_app_my_demo.7z

    通过这个"web_app_my_demo.7z"项目,开发者可以深入理解Flutter_web的工作原理,学习如何构建Web应用,并逐步提升在Web开发领域的技能。同时,这也是一个实践性的学习机会,有助于熟悉Dart语言和Flutter的开发流程。

    小龟视频APP双端影视对接苹果CMS反编译源码+视频教程

    在反编译源码的过程中,开发者可以深入理解APP的工作原理,学习如何解析和处理来自CMS的数据,例如视频URL、元数据、评论等。反编译可能涉及的工具有Apktool、dex2jar等,这些工具可以帮助开发者解包APK,查看和修改...

    详解flutter engine 那些没被释放的东西

    开发者需要密切关注官方更新,理解引擎内部的工作原理,并通过优化代码来确保内存的有效利用。此外,定期检查和测试内存使用情况,结合工具进行内存分析,也能帮助找出并修复潜在的内存泄漏问题。

    flutter_app2

    Flutter_app2 是一个基于Dart语言开发的移动应用程序项目,主要使用Flutter框架构建。...通过研究和理解这个项目,开发者可以深入理解Flutter的工作原理和最佳实践,并提升自己的移动应用开发技能。

    Flutter网站

    【标题】:Flutter网站开发详解 【描述】:Flutter,Google推出的一款开源UI工具包,以其高效的跨平台开发能力和...通过理解Flutter Web的原理、组件、JavaScript交互以及优化策略,开发者能够构建出高质量的Web应用。

    flutter_calculator

    【Flutter Calculator 应用程序详解】 Flutter Calculator 是一个基于Dart语言开发的简单计算器应用,其设计灵感来自于...在深入理解这些基础知识后,开发者可以进一步扩展和定制,创造出更加复杂和功能丰富的应用。

    能编译过的xeim源码

    6. **安全性**:包括数据加密、防止DDoS攻击、用户隐私保护等,需要对网络安全有深入理解。 7. **跨平台开发**:xeim作为一款IM软件,可能需要在多个操作系统上运行,所以开发者需要熟悉跨平台开发工具和技术,如...

    Android系统原理及开发要点详解PDF扫描.韩超,梁泉

    本书全面覆盖了Android系统的底层机制、应用程序开发的关键技术和实践要点,对于想要深入理解Android并提升开发技能的工程师来说,是一本不可多得的参考资料。 在Android系统原理部分,书中详细讲解了以下核心概念...

    try_flutter:尝试学习颤振并为其添加火力基础

    总的来说,“try_flutter”项目提供了一个很好的学习平台,让开发者可以通过实践了解Flutter和Dart语言的各个方面,包括UI设计、状态管理、路由、动画以及原生平台交互。通过研究和运行这个项目,你不仅可以掌握...

Global site tag (gtag.js) - Google Analytics