Flutter 高性能原理淺析

Flutter 高性能原理淺析

[圖片上傳失敗...(image-1a480b-1642738386010)]

北斗星_And關(guān)注

1<time datetime="2019-07-29T01:34:03.000Z" style="box-sizing: border-box; margin-right: 10px;">2019.07.29 09:34:03</time>字數(shù) 2,470閱讀 4,273

<article class="_2rhmJa" style="box-sizing: border-box; display: block; font-weight: 400; line-height: 1.8; margin-bottom: 20px; word-break: break-word; position: relative;">

這是我第三篇Flutter相關(guān)博客
歡迎 查看我的前兩篇 Flutter實現(xiàn)篇

前言

Flutter是Google用以幫助開發(fā)者在Ios和Android兩個平臺開發(fā)高質(zhì)量原生應用的全新移動UI框架.我開始認識Flutter時,經(jīng)歷了三個Flutter重要歷史版本.

  • 2018年2月27日捺典,在2018世界移動大會上鸟廓,Google發(fā)布了Flutter的第一個Beta版本。
  • 2018年6月21日襟己,在全球大前端技術(shù)大會上肝箱,發(fā)布了第一個Release Perview 1版本。
  • 2018年12月5日第一個Release 1.0版本發(fā)布.

此后越來越多的人開始關(guān)注到Flutter稀蟋。

在 Flutter 誕生之前煌张,已經(jīng)有許多跨平臺 UI 框架的方案,比如基于 WebView 的 Cordova退客、AppCan 等骏融,還有使用 HTML+JavaScript 渲染成原生控件的 React Native、Weex 等萌狂。Flutter 則開辟了一種全新的思路档玻,從頭到 尾重寫一套跨平臺的 UI 框架,包括 UI 控件茫藏、渲染邏輯甚至開發(fā)語言误趴。

Flutter框架

image

從圖中可以看出 Flutter主要被分為兩層 Framework層和Flutter Engine.

Framework層全部使用Dart編寫,有完整UI框架的API务傲,并預寫了Android(MaterialDesign)和IOS的(Cupertino)風格的UI,極大方便了開發(fā)移動端.

Framework 底層是 Flutter 引擎凉当, 引擎主要負責圖形繪制 (Skia)、 文字排版 (libtxt) 和提供 Dart 運行時售葡, 引擎全部使用 C++實現(xiàn).

Flutter高性能原理

與其他跨平臺框架對比

在看Flutter框架前看杭,我們先看一下其他跨平臺框架的設計

image

看Hybrid的架構(gòu),我們可以知道UI層的渲染是基于Webview去渲染挟伙,他的性能取決于webview的渲染性能楼雹,目前已知webview渲染性能 < NativeUI的性能

image

RN/Weex 的架構(gòu)中,是基于Native的UI框架去適配,中間多了一層js轉(zhuǎn)NativeUI的過程

image

而Flutter不需要中間層(Webview贮缅,js 轉(zhuǎn)NativeUI這個過程)榨咐,他是基于圖像渲染引擎去直接繪制UI.

Dart 對于UI框架的高性能支持

我們知道Flutter的Framework層是使用了Dart語言編寫,那Dart語言有哪些優(yōu)勢呢谴供?下面分為幾個點來闡述

Dart內(nèi)存分配機制

DartVM的內(nèi)存分配策略非常簡單块茁,創(chuàng)建對象時只需要在現(xiàn)有堆上移動指針,內(nèi)存增長始終是線形的,省去了查找可用內(nèi)存段的過程

image

Dart中類似線程的概念叫做Isolate憔鬼,每個Isolate之間是無法共享內(nèi)存的龟劲,所以這種分配策略可以讓Dart實現(xiàn)無鎖的快速分配胃夏。

Dart 垃圾回收機制

Dart的垃圾回收也采用了多生代算法轴或,新生代在回收內(nèi)存時采用了“半空間”算法,觸發(fā)垃圾回收時Dart會將當前半空間中的“活躍”對象拷貝到備用空間仰禀,然后整體釋放當前空間的所有內(nèi)存如圖.

image

整個過程中Dart只需要操作少量的“活躍”對象照雁,大量的沒有引用的“死亡”對象則被忽略,這種 多生代無鎖垃圾回收器答恶,專門為UI框架中常見的大量Widgets對象創(chuàng)建和銷毀優(yōu)化,非常適合Flutter框架中大量Widget重建的場景.

Dart 編體積優(yōu)化饺蚊,及編譯JIT和AOT支持

代碼體積優(yōu)化(Tree Shaking),編譯時只保留運行時需要調(diào)用的代碼(不允許反射這樣的隱式引用)悬嗓,所以龐大的Widgets庫不會造成發(fā)布體積過大污呼。

Dart支持兩種編譯模式:

  • JIT編譯 Just In Time Compiler -即時編譯
  • AOT編譯Ahead Of Time 預編譯

在debug模式下使用JIT編譯,生成srcipt/bytecode進行解釋執(zhí)行包竹,可以支持HotReload(熱重載)燕酷,修改代碼,保持即可在設備上看到效果. 而在Release下 AOT編譯生成Machine Code周瞎,高效的運行.

Dart 單線程 異步消息機制

客戶端交互簡述

對于移動端的交互來說苗缩,大多數(shù)情況下都是在等待狀態(tài),等待網(wǎng)絡請求声诸,等待用戶輸入等.那么設想一下酱讶,發(fā)起一個網(wǎng)絡請求只在一個線程中可以進行嗎?當然網(wǎng)絡請求肯定是異步的(注意這里說的異步而多線程并非一個概念.)彼乌,事實驗證是可以的泻肯,F(xiàn)lutter就采用了Dart這種單線程機制,省去了多線程上下文切換帶來的性能損耗.(對于高耗時操作慰照,也同樣支持多線程操作软免,通過Isolate開啟,不過注意這里的多線程焚挠,內(nèi)存是無法共享的.)

Dart 異步消息原理

當一個Dart的方法開始執(zhí)行時膏萧,他會一直執(zhí)行直至達到這個方法的退出點。換句話說Dart的方法是不會被其他Dart代碼打斷的。
當一個Dart應用開始的標志是它的main isolate執(zhí)行了main方法榛泛。當main方法退出后蝌蹂,main isolate的線程就會去逐一處理消息隊列中的消息。

image

有了消息隊列曹锨,然后有了循環(huán)去讀取消息隊列中的消息孤个,就可以有單線程去執(zhí)行異步消息的能力.
一般的消息使用dart:async中使用Future來支持異步消息.

Flutter Engine 高性能

在講Flutter Engin層時,我們先講一下屏幕繪制的原理.

屏幕繪制原理

image

我們都知道顯示器以固定的頻率刷新沛简,比如 iPhone的 60Hz齐鲤、iPad Pro的 120Hz。當一幀圖像繪制完畢后準備繪制下一幀時椒楣,顯示器會發(fā)出一個垂直同步信號(VSync)给郊,所以 60Hz的屏幕就會一秒內(nèi)發(fā)出 60次這樣的信號。

并且一般地來說捧灰,計算機系統(tǒng)中淆九,CPU、GPU和顯示器以一種特定的方式協(xié)作:CPU將計算好的顯示內(nèi)容提交給 GPU毛俏,GPU渲染后放入幀緩沖區(qū)炭庙,然后視頻控制器按照 VSync信號從幀緩沖區(qū)取幀數(shù)據(jù)傳遞給顯示器顯示。

作為一個專職Android開發(fā)煌寇,看過Android的繪圖機制焕蹄,通過SurfaceFlinger 和HAL層之間的工作機制發(fā)現(xiàn)和Flutter的很像,那么IOS的如何呢阀溶?個人推測屏幕的繪圖機制是一樣的腻脏,只是不同平臺有不同實現(xiàn).

Flutter Engine的渲染機制

image

Flutter只關(guān)心向 GPU提供視圖數(shù)據(jù),GPU的 VSync信號同步到 UI線程淌哟,UI線程使用 Dart來構(gòu)建抽象的視圖結(jié)構(gòu)迹卢,這份數(shù)據(jù)結(jié)構(gòu)在 GPU線程進行圖層合成,視圖數(shù)據(jù)提供給 Skia引擎渲染為 GPU數(shù)據(jù)徒仓,這些數(shù)據(jù)通過 OpenGL或者 Vulkan提供給 GPU.

所以 Flutter并不關(guān)心顯示器腐碱、視頻控制器以及 GPU具體工作,它只關(guān)心 GPU發(fā)出的 VSync信號掉弛,盡可能快地在兩個 VSync信號之間計算并合成視圖數(shù)據(jù)症见,并且把數(shù)據(jù)提供給 GPU.

Flutter Framework層的繪圖機制

UI樹原理

image

在 Flutter 界面渲染過程分為 3 個階段: 布局、繪制殃饿、合成.

而布局階段谋作,有三個重要的對象.RenderObject、Element乎芳、Widget.

image
  • Widget是開發(fā)經(jīng)常接觸的控件,默認是只讀的.

  • Element 是 Flutter 用來分離控件樹和真正的渲染 對象的中間層遵蚜, 控件用來描述對應的 element 屬性帖池,控件重建后可能會復用同一個 element.

  • RenderObject 負責提供配置信息并創(chuàng)建具體的 Element。

Element 持有真正負責布局吭净、 繪制和碰撞測試 (hit test) 的 RenderObject 對象.

那么這樣睡汹,如果控件的屬性發(fā)生了變化 (因為控件的屬性是只 讀的, 所以變化也就意味著重新創(chuàng)建了新的控件樹)寂殉, 但是其樹上每個節(jié)點的類型沒有變化時囚巴, element 樹和 render 樹可以完全重用原來的對象 (因為 element 和 render object 的屬性都是可變的)

布局原理

傳統(tǒng)布局,如Android可能需要多次Measure,計算寬高友扰。Flutter 采用約束進行單次測量布局. 整個布局過程中只需要深度遍歷一次彤叉,極大的提升效能。

image

渲染對象樹中的每個對象都會在布局過程中接受父 對象的 Constraints 參數(shù),決定自己的大小, 然后父對象 就可以按照自己的邏輯決定各個子對象的位置,完成布局過程.

子對象不存儲自己在容器中的位置村怪, 所以在它的位置發(fā)生改變時并不需要重新布局或者繪制. 子對象的位 置信息存儲在它自己的 parentData 字段中,但是該字段由它的父對象負責維護,自身并不關(guān)心該字段的內(nèi)容秽浇。

同時也因為這種簡單的布局邏輯, Flutter 可以在某些節(jié) 點設置布局邊界 (Relayout boundary)实愚, 即當邊界內(nèi)的任 何對象發(fā)生重新布局時兼呵, 不會影響邊界外的對象兔辅, 反之亦然.

</article>

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末腊敲,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子维苔,更是在濱河造成了極大的恐慌碰辅,老刑警劉巖,帶你破解...
    沈念sama閱讀 207,113評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件介时,死亡現(xiàn)場離奇詭異没宾,居然都是意外死亡,警方通過查閱死者的電腦和手機沸柔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評論 2 381
  • 文/潘曉璐 我一進店門循衰,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人褐澎,你說我怎么就攤上這事会钝。” “怎么了工三?”我有些...
    開封第一講書人閱讀 153,340評論 0 344
  • 文/不壞的土叔 我叫張陵迁酸,是天一觀的道長。 經(jīng)常有香客問我俭正,道長奸鬓,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,449評論 1 279
  • 正文 為了忘掉前任掸读,我火速辦了婚禮串远,結(jié)果婚禮上宏多,老公的妹妹穿的比我還像新娘。我一直安慰自己澡罚,他們只是感情好绷落,可當我...
    茶點故事閱讀 64,445評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著始苇,像睡著了一般砌烁。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上催式,一...
    開封第一講書人閱讀 49,166評論 1 284
  • 那天函喉,我揣著相機與錄音,去河邊找鬼荣月。 笑死管呵,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的哺窄。 我是一名探鬼主播捐下,決...
    沈念sama閱讀 38,442評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼萌业!你這毒婦竟也來了坷襟?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評論 0 261
  • 序言:老撾萬榮一對情侶失蹤生年,失蹤者是張志新(化名)和其女友劉穎婴程,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抱婉,經(jīng)...
    沈念sama閱讀 43,601評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡档叔,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,066評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蒸绩。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衙四。...
    茶點故事閱讀 38,161評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖患亿,靈堂內(nèi)的尸體忽然破棺而出传蹈,到底是詐尸還是另有隱情,我是刑警寧澤窍育,帶...
    沈念sama閱讀 33,792評論 4 323
  • 正文 年R本政府宣布史煎,位于F島的核電站驮审,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蛀醉,卻給世界環(huán)境...
    茶點故事閱讀 39,351評論 3 307
  • 文/蒙蒙 一附迷、第九天 我趴在偏房一處隱蔽的房頂上張望钾怔。 院中可真熱鬧,春花似錦显歧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蕾域,卻和暖如春拷肌,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背旨巷。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評論 1 261
  • 我被黑心中介騙來泰國打工巨缘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人采呐。 一個月前我還...
    沈念sama閱讀 45,618評論 2 355
  • 正文 我出身青樓若锁,卻偏偏與公主長得像,于是被迫代替她去往敵國和親斧吐。 傳聞我的和親對象是個殘疾皇子又固,可洞房花燭夜當晚...
    茶點故事閱讀 42,916評論 2 344

推薦閱讀更多精彩內(nèi)容