轉(zhuǎn)載:Flutter的編譯模式

原文鏈接 https://www.stephenw.cc/2018/07/30/flutter-compile-mode/

Flutter的編譯模式

Jul 30, 2018

使用 Flutter構(gòu)建過(guò) App的人一定有一個(gè)困惑杰扫,就是 Flutter編譯出的產(chǎn)物到底是什么玩意增拥,有時(shí)候分為幾個(gè)文件,有時(shí)候是一個(gè)動(dòng)態(tài)庫(kù)具温,真的叫人摸不著頭腦薪韩。
本文詳細(xì)解釋一下 Flutter的編譯模式穷蛹。

編譯模式的分類.

編程語(yǔ)言要達(dá)到可運(yùn)行的目的需要經(jīng)過(guò)編譯偶惠,一般地來(lái)說(shuō),編譯模式分為兩類:JIT 和 AOT光坝。

JIT:

JIT全稱 Just In Time(即時(shí)編譯)尸诽,典型的例子就是 v8,它可以即時(shí)編譯并運(yùn)行 JavaScript盯另。所以你只需要輸入源代碼字符串性含,v8就可以幫你編譯并運(yùn)行代碼。通常來(lái)說(shuō)鸳惯,支持 JIT的語(yǔ)言一般能夠支持自省函數(shù)(eval)商蕴,在運(yùn)行時(shí)動(dòng)態(tài)地執(zhí)行代碼。
JIT模式的優(yōu)勢(shì)是顯而易見的悲敷,可以動(dòng)態(tài)下發(fā)和執(zhí)行代碼究恤,而不用管用戶的機(jī)器是什么架構(gòu),為應(yīng)用的用戶提供豐富而動(dòng)態(tài)地內(nèi)容后德。
但 JIT的劣勢(shì)也是顯而易見的部宿,大量字符串的代碼很容易讓 JIT編譯器花費(fèi)很多時(shí)間和內(nèi)存進(jìn)行編譯,給用戶帶來(lái)的直接感受就是應(yīng)用啟動(dòng)慢瓢湃。

AOT:

AOT全稱 Ahead Of Time(事前編譯)理张,典型的例子就是 C/C++,LLVM或 GCC通過(guò)編譯并生成 C/C++的二進(jìn)制代碼绵患,然后這些二進(jìn)制通過(guò)用戶安裝并取得執(zhí)行權(quán)限后才可以通過(guò)進(jìn)程加載執(zhí)行雾叭。
AOT的優(yōu)勢(shì)也是顯而易見的,事先編譯好的二進(jìn)制代碼落蝙,加載和執(zhí)行的速度都會(huì)非持快暂幼。(所以編程語(yǔ)言速度排行榜上前列都是 AOT編譯類語(yǔ)言)這樣的速度可以在密集計(jì)算場(chǎng)景下給用戶帶來(lái)非常好的體驗(yàn),比如大型游戲的引擎渲染和邏輯執(zhí)行移迫。

但是 AOT的劣勢(shì)也是顯而易見的旺嬉,編譯需要區(qū)分用戶機(jī)器的架構(gòu),生成不同架構(gòu)的二進(jìn)制代碼厨埋,除了架構(gòu)邪媳,二進(jìn)制代碼本身也會(huì)讓用戶下載的安裝包比較大。二進(jìn)制代碼一般需要取得執(zhí)行權(quán)限才可以執(zhí)行荡陷,所以無(wú)法在權(quán)限比較嚴(yán)格的系統(tǒng)中進(jìn)行動(dòng)態(tài)更新(如 iOS)雨效。

Dart的編譯模式

Flutter使用 Dart作為編程語(yǔ)言,自然其編譯模式也脫離不了 Dart的干系废赞。首先我們需要了解一下 Dart所支持的編譯模式徽龟。

  • Script:最普通的 JIT模式,在 PC命令行調(diào)用 dart vm執(zhí)行 dart源代碼文件即是這種模式蛹头。
  • Script Snapshot:JIT模式顿肺,和上一個(gè)不同的是戏溺,這里載入的是已經(jīng) token化的 dart源代碼渣蜗,提前執(zhí)行了上一步的 lexer步驟。
  • Application Snapshot:JIT模式旷祸,這種模式來(lái)源于 dart vm直接載入源碼后 dump出數(shù)據(jù)耕拷。dart vm通過(guò)這種數(shù)據(jù)啟動(dòng)會(huì)更快。不過(guò)值得一提的是這種模式是區(qū)分架構(gòu)的托享,在 x64上生成的數(shù)據(jù)不可以給 arm使用骚烧。
  • AOT:AOT模式,直接將 dart源碼編譯出 .S文件闰围,然后通過(guò)匯編器生成對(duì)應(yīng)架構(gòu)的代碼赃绊。

總結(jié)一下剛才的列表,可以發(fā)現(xiàn):

模式/比較項(xiàng) 編譯模式 區(qū)分架構(gòu) 打包大小 動(dòng)態(tài)化
Script JIT
Script Snapshot JIT 很小
Application Snapshot JIT 比較大 是(注意架構(gòu))
AOT AOT 比較大

Flutter的編譯模式

Flutter 完全采用了 Dart羡榴,按道理來(lái)說(shuō)編譯模式一致才是碧查,但是事實(shí)并不是這樣。由于 Android和 iOS平臺(tái)的生態(tài)差異校仑,F(xiàn)lutter也衍生除了非常豐富的編譯模式忠售。

  • Script:同 Dart Script模式一致,雖然 Flutter支持迄沫,但暫未看到使用稻扬,畢竟影響啟動(dòng)速度。
  • Script Snapshot:同 Dart Script Snapshot一致羊瘩,同樣支持但未使用泰佳,F(xiàn)lutter有大量的視圖渲染邏輯盼砍,純 JIT模式影響執(zhí)行速度。
  • Kernel Snapshot:Dart的 bytecode 模式逝她,與 Application Snapshot不同衬廷,bytecode模式是不區(qū)分架構(gòu)的。 Kernel Snapshot在 Flutter項(xiàng)目?jī)?nèi)也叫 Core Snapshot汽绢。bytecode模式可以歸類為 AOT編譯吗跋。
  • Core JIT:Dart的一種二進(jìn)制模式,將指令代碼和 heap數(shù)據(jù)打包成文件宁昭,然后在 vm和 isolate啟動(dòng)時(shí)載入跌宛,直接標(biāo)記內(nèi)存可執(zhí)行,可以說(shuō)這是一種 AOT模式积仗。Core JIT也被叫做 AOTBlob
  • AOT Assembly: 即 Dart的 AOT模式疆拘。直接生成匯編源代碼文件,由各平臺(tái)自行匯編寂曹。

可以看出來(lái)哎迄,F(xiàn)lutter將 Dart的編譯模式復(fù)雜化了,多了不少概念隆圆,要一下敘述清楚是比較困難的漱挚,所以我們著重從 Flutter應(yīng)用開發(fā)的各個(gè)階段來(lái)解讀。

開發(fā)階段的編譯模式

在開發(fā)階段渺氧,我們需要 Flutter的 Hot Reload和 Hot Restart功能旨涝,方便 UI快速成型。同時(shí)侣背,框架層也需要比較高的性能來(lái)進(jìn)行視圖渲染展現(xiàn)白华。因此開發(fā)模式下,F(xiàn)lutter使用了 Kernel Snapshot模式編譯贩耐。
在打包產(chǎn)物中弧腥,你將發(fā)現(xiàn)幾樣?xùn)|西:

  • isolate_snapshot_data:用于加速 isolate啟動(dòng),業(yè)務(wù)無(wú)關(guān)代碼潮太,固定管搪,僅和 flutter engine版本有關(guān)
  • platform.dill:和 dart vm相關(guān)的 kernel代碼,僅和 dart版本以及 engine編譯版本有關(guān)消别。固定抛蚤,業(yè)務(wù)無(wú)關(guān)代碼。
  • vm_snapshot_data: 用于加速 dart vm啟動(dòng)的產(chǎn)物寻狂,業(yè)務(wù)無(wú)關(guān)代碼岁经,僅和 flutter engine版本有關(guān)
  • kernel_blob.bin:業(yè)務(wù)代碼產(chǎn)物
項(xiàng)目/平臺(tái) Android iOS
代碼環(huán)境 debug debug
編譯模式 Kernel Snapshot Kernel Snapshot
打包工具 dart vm (2.0) dart vm (2.0)
Flutter命令 flutter build bundle flutter build bundle
打包產(chǎn)物 flutter_assets/* flutter_assets/*

生產(chǎn)階段的編譯模式

在生產(chǎn)階段,應(yīng)用需要的是非成呷快的速度缀壤,所以 Android和 iOS target毫無(wú)意外地都選擇了 AOT打包樊拓。不過(guò)由于平臺(tái)特性不同,打包模式也是天壤之別塘慕。

項(xiàng)目/平臺(tái) Android iOS Android(–build-shared-library)
代碼環(huán)境 release release release
編譯模式 Core JIT AOT Assembly AOT Assembly
打包工具 gen_snapshot gen_snapshot gen_snapshot
Flutter命令 flutter build aot flutter build aot –ios flutter build aot –build-shared-library
打包產(chǎn)物 flutter_assets/* App.framework app.so

首先我們很容易認(rèn)識(shí)到 iOS平臺(tái)上做法的原因:App Store審核條例不允許動(dòng)態(tài)下發(fā)可執(zhí)行二進(jìn)制代碼筋夏。
所以在 iOS上,除了 JavaScript图呢,其他語(yǔ)言運(yùn)行時(shí)的實(shí)現(xiàn)都選擇了 AOT条篷。(比如 OpenJDK在 iOS實(shí)現(xiàn)就是 AOT)

在 Android上,F(xiàn)lutter的做法有點(diǎn)意思:支持了兩種不同的路子蛤织。
Core JIT的打包產(chǎn)物有 4個(gè):isolate_snapshot_data, vm_snapshot_data, isolate_snapshot_instr, vm_snapshot_instr. 我們不認(rèn)識(shí)的產(chǎn)物只有 2個(gè):isolate_snapshot_instr和 vm_snapshot_instr赴叹,其實(shí)它倆代表著 vm和 isolate啟動(dòng)后所承載的指令等數(shù)據(jù),在載入后指蚜,直接將該塊內(nèi)存執(zhí)行即可乞巧。
Android的 AOT Assembly打包方式很容易讓人想到需要支持多架構(gòu),無(wú)疑增大了代碼包摊鸡,并且該處代碼需要從 JNI調(diào)用绽媒,遠(yuǎn)不如 Core JIT的 Java API方便。所以 Android上默認(rèn)使用 Core JIT打包免猾,而不是 AOT Assembly是辕。

Flutter Engine對(duì)編譯模式的支持

在我的上篇文章:Flutter原理簡(jiǎn)解中提到,engine承載了 dart運(yùn)行時(shí)掸刊,毫無(wú)疑問(wèn) engine需要和打包出來(lái)的代碼對(duì)的上號(hào)才行免糕。
在 engine的編譯模式中,F(xiàn)lutter是這樣選擇的:

項(xiàng)目/平臺(tái) iOS Android
Script 不支持 不支持
ScriptSnapshot 理論支持 理論支持
Kernel Snapshot 支持忧侧,runmode = dynamic 支持,runmode = dynamic
CoreJIT 不支持 支持
AOT Assembly 支持 支持

所以我們可以看到牌芋,F(xiàn)lutter的編譯模式是完全根據(jù) Engine的支持度來(lái)設(shè)計(jì)的蚓炬。

結(jié)論

看到這里,我們完全可以得出一個(gè)結(jié)論:Flutter是一種高性能的躺屁、可跨平臺(tái)的肯夏、動(dòng)態(tài)化應(yīng)用開發(fā)方案。
在 iOS和 Android平臺(tái)上犀暑,動(dòng)態(tài)化完全可由 Kernel Snapshot打包實(shí)現(xiàn)驯击,并且產(chǎn)物是一致通用的。不過(guò)目前通過(guò)打包工具進(jìn)行了閹割耐亏,只能生成 debug產(chǎn)物徊都。
并且如果不需要?jiǎng)討B(tài)化,同樣可以打包出擁有更高執(zhí)行性能的二進(jìn)制庫(kù)文件使用广辰。這個(gè)特性目前就已經(jīng)支持

有了理論的支持暇矫,我們就可以著手做改造的事了主之。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市李根,隨后出現(xiàn)的幾起案子槽奕,更是在濱河造成了極大的恐慌,老刑警劉巖房轿,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件粤攒,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡囱持,警方通過(guò)查閱死者的電腦和手機(jī)琼讽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洪唐,“玉大人钻蹬,你說(shuō)我怎么就攤上這事∑拘瑁” “怎么了问欠?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)粒蜈。 經(jīng)常有香客問(wèn)我顺献,道長(zhǎng),這世上最難降的妖魔是什么枯怖? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任注整,我火速辦了婚禮,結(jié)果婚禮上度硝,老公的妹妹穿的比我還像新娘肿轨。我一直安慰自己,他們只是感情好蕊程,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布椒袍。 她就那樣靜靜地躺著,像睡著了一般藻茂。 火紅的嫁衣襯著肌膚如雪驹暑。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天辨赐,我揣著相機(jī)與錄音优俘,去河邊找鬼。 笑死掀序,一個(gè)胖子當(dāng)著我的面吹牛帆焕,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播森枪,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼视搏,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼审孽!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起浑娜,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤佑力,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后筋遭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體打颤,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年漓滔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了编饺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡响驴,死狀恐怖透且,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情豁鲤,我是刑警寧澤秽誊,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站琳骡,受9級(jí)特大地震影響锅论,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜楣号,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一最易、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧炫狱,春花似錦藻懒、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至憎亚,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間弄慰,已是汗流浹背第美。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陆爽,地道東北人什往。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像慌闭,于是被迫代替她去往敵國(guó)和親别威。 傳聞我的和親對(duì)象是個(gè)殘疾皇子躯舔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354