iOS:原生應用 VS Flutter VS GICXMLLayout 比較
最近,有些朋友問我,到底 GICXMLLayout
的效能如何?因此有了本篇文章。另外,考慮到現在 Flutter
也比較火,為了不藏私,因此也加入對 Flutter
的比較。因此這裡詳細的對三種開發方式進行橫向比較。
注1: flutter
採用的是最新的 1.0.0
版本。
注2: flutter
的測試都在 profile
模式下測試,效能接近 release
。
文中用到的測試程式碼可以直接從這裡 點選下載
在做比較之前,先確定一個比較的樣例。這裡以如下UI內容為例。

這裡面給出了一個顯示可變高度的列表的案例,這樣的案例比較具有通用性,有圖片的載入、有高度不固定文字的顯示、有高度不固定CellHeight的計算等等。下面針對這樣的案例,從各種角度來比較分析在不同的開發方式下的比較。
1. 啟動時間
測試平臺是 iPhoneX
, iOS 12.0
,因為做的是橫向比較,因此不在多裝置上進行測試,只在 iPhoneX
上進行測試分析。
啟動時間的比較由兩個方面組成。
-
main
之前main
函式之前的時間表示的是iOS對動態連結庫的載入、系統載入等所耗時間。這個時間通過新增DYLD_PRINT_STATISTICS
巨集來獲得。 -
main
函式之後main
函式之後的時間通過main
函式和applicationDidBecomeActive:
方法的時間差來獲得。
另外,為了公平起見,測試方式採用的 profile
的方式測試。
主要是考慮到 Flutter
在 release
和 debug
兩種模式下的效能差異太大,而 release
和 profile
兩種模式很接近,因此採用 profile
的方式
另外,測試載入的資料為11條,時間單位為(秒)
原生
main
函式之前的時間範例
Total pre-main time: 205.82 milliseconds (100.0%) dylib loading time: 191.47 milliseconds (93.0%) rebase/binding time:0.29 milliseconds (0.1%) ObjC setup time:6.29 milliseconds (3.0%) initializer time:7.76 milliseconds (3.7%) slowest intializers : libSystem.B.dylib :4.67 milliseconds (2.2%) 複製程式碼
main之前 | mian之後 | 總計 |
---|---|---|
0.201 | 0.099 | 0.3 |
0.206 | 0.086 | 0.292 |
0.210 | 0.092 | 0.302 |
0.197 | 0.089 | 0.286 |
0.195 | 0.098 | 0.293 |
平均 | 0.294 |
以上資料是原生APP的啟動時間,平均 0.294秒
GICXMLLayout
main
函式之前的時間範例
Total pre-main time: 342.71 milliseconds (100.0%) dylib loading time: 291.83 milliseconds (85.1%) rebase/binding time:1.55 milliseconds (0.4%) ObjC setup time:15 .76 milliseconds (4.5%) initializer time:33.48 milliseconds (9.7%) slowest intializers : libSystem.B.dylib :7.05 milliseconds (2.0%) AsyncDisplayKit :42.27 milliseconds (12.3%) 複製程式碼
main之前 | mian之後 | 總計 |
---|---|---|
0.318 | 0.066 | 0.384 |
0.342 | 0.069 | 0.411 |
0.338 | 0.066 | 0.404 |
0.337 | 0.067 | 0.404 |
0.330 | 0.064 | 0.394 |
平均 | 0.399 |
Flutter
main
函式之前的執行時間範例
Total pre-main time: 206.08 milliseconds (100.0%) dylib loading time: 189.66 milliseconds (92.0%) rebase/binding time:0.82 milliseconds (0.3%) ObjC setup time:7.52 milliseconds (3.6%) initializer time:8.06 milliseconds (3.9%) slowest intializers : libSystem.B.dylib :4.61 milliseconds (2.2%) 複製程式碼
main之前 | mian之後 | 總計 |
---|---|---|
0.218 | 0.115 | 0.333 |
0.203 | 0.105 | 0.308 |
0.209 | 0.113 | 0.322 |
0.211 | 0.110 | 0.321 |
0.203 | 0.107 | 0.310 |
平均 | 0.319 |
分析
通過以上三種開發方式的資料分析可以看出,
- 啟動時間最短的是
原生應用
,最長的是GIC
的應用。 -
GIC
之所以最長,是因為在main
函式之前載入了太多的第三方庫,但是可以看到main
函式之後的執行時間是最短的。 -
flutter
在release
模式下的main
函式之前的載入時間跟原生應用可以說相差無幾,從這裡可以看出,大廠就是大廠,技術能力不得不服。 -
flutter
在main
函式之後的執行時間是三種方式中是最長的。flutter
的引擎、UI、GPU相關的操作都有專門的執行緒負責,區別於iOS
中的UI執行緒
。而flutter
在main
函式之後的執行時間卻是最長的,那麼說明,flutter
有些初始化操作可能是在iOS的UI執行緒
中執行的。考慮到Flutter
app載入了一個Flutter.framework
,並且包含了對iOS
平臺呼叫的程式碼(FlutterAppDelegate
、FlutterViewController
等),因此初步判斷是這個庫中的程式碼的執行結果。 -
GIC
的main
之後執行時間最短應該說是情理之中,因為GIC
的列表佈局
、渲染
等都在非UI執行緒執行的(得益於Texture
)。也就是說,GIC
在UI執行緒上做的事情是在三種開發方式中最少的。
從這裡也可以看出, GIC
的問題在於對第三方庫的依賴太多,後續考慮如何減少對第三方庫的依賴,事實上目前已經在做對 RAC
庫的剝離工作,相信剝離後會進一步的提升載入速度。
原生應用
在載入列表的時候採用的是最粗暴的方法,沒有任何的優化,沒有height快取,沒有在後臺執行緒做height計算等等,因此原生應用在啟動時間方面也有進一步的優化空間。但是排名不會發生變化,最多就是 mian
函式後的執行時間會縮短,但不會短過 GIC
。
2. 幀率
、 CPU
、 GPU
這三項資料的測試在iPhoneX上看不出明顯的不同,因此這裡就以 iphone 6
的測試資料為準。
測試方式:不停的滑動列表
原生


GICXMLLayout


flutter


分析
- 幀率:
在幀率方面,三種方式都差不多,基本上都能維持滿幀。
- CPU:
CPU佔用率從高到低排名為:
flutter
(平均14%) > 原生(平均10%) >GIC
(平均7%)。 - GPU:
GPU佔用率從高到低排名為:
flutter
(平均22%) > 原生(平均16%) >GIC
(平均12%)。跟CPU的結果差不多,flutter
在滑動的時候GPU耗費也高達22%,比最低的GIC
差不多高了一倍。
這一輪的測試中, flutter
基本上算是完敗了,不是百分之多少的差距,而是成倍的差距。
GIC
在UI層是基於 Textrue
開發的,因此繼承了 Textrue
的所有優點。在這一輪測試中可以說完勝。
3. 記憶體佔用
測試方式:頁面載入完成後滑動列表,然後靜置一段時間 測試裝置:iphone6
原生

GICXMLLayout

flutter
flutter
依然是以 profile
模式測試。

分析
由上面三張圖看出, flutter
(40MB)佔用的記憶體最多, GIC
(13.7MB)次之, 原生
(9MB)應用佔用最少。
- 可以看出
flutter
佔用了40MB,比原生應用多了將近3倍都不止。 - 而
GIC
佔用了13.7MB
。由於
GIC
在基於Texuture
封裝的時候把佈局元素也作為UI元素
封裝了,因此導致實際的記憶體佔用稍微高了點。
另外, GIC
在使用的過程中建立了 JSContext
,你可以理解為JS引擎。而在實際使用過程中,JS並沒有佔用太多的記憶體。當然,這裡面涉及到JS功能也比較少,因此也無法直接說JS佔用記憶體地。
4. 包大小。
為了公平起見,這裡的測試基於 release
模式下測試。另外,在開啟和關閉 bitcode
兩種模式下,包的大小差距會很大。這裡分別給出。
另外,測試應用已經踢除了靜態圖片資源。
原生
bitcode bitcode
GICXMLLayout
bitcode bitcode
flutter
flutter
本身就不支援bitcode。因此忽略bitcode。包的大小為:11MB
分析
通過上面的資料可以分析出,在關閉bitcode的情況下,包的大小依次為, flutter
(11MB) > GIC
(3.7MB) > 原生(269KB)。
5. 動畫
這裡以一個簡單的水平位移動畫作為案例。

測試裝置:iphone6
原生
使用 CABasicAnimation
做動畫。

GICXMLLayout

flutter

分析
對於這麼簡單的動畫,都是滿幀執行的。因此只需要對GPU和CPU做分析比較即可。
-
原生
:原生方式的效能表現是最好的。在動畫的時候,幾乎不佔用CPU資源。而GPU一直保持著7%的佔用。
-
GICXMLLayout
:GIC
的GPU的佔用上跟原生的差不多,但是CPU卻一直有佔用,差不多維持著最高10%
的佔用。並且可以注意到,CPU的佔用不是連續的而是斷斷續續的,這是有原因的,因為GIC
的動畫是基於popAnimation
實現的,而popAnimation
是基於CADisplaylink
開發的,並且是按照60幀計算的。也就是差不多每秒60次的動畫計算。而只有在動畫計算的時候才會佔用CPU資源,因此從測試結果來看,也是符合預期的。另外,在記憶體佔用方面,跟原生動畫差不多。 -
flutter
flutter
的動畫在GPU的佔用上幾乎是原生的兩倍以上。而且CPU也是連續維持著10%的佔用。而記憶體佔用方面也差不多是原生的兩倍以上。
總結
在上面的測試中,由於測試案例比較簡單,並不能代表大多數情況,只是針對當前的測試案例得出的結果,僅僅只是給出一個參考。
對於原生引用的測試程式碼可能有點不公平,沒有進行任何的優化。然而這並不是關鍵,這樣正說明了原生應用的優化空間比較大。
本來還想做一個 列表載入時間
測試的,但是對於 flutter
卻無從下手,暫時不知道如何測試,等以後有方法了再做測試。
另外,這裡也不得不為我自己的 GICXMLLayout
做個宣傳。作為一個獨立開發者維護的一個開源庫並不容易,我花了很多的心血在這上面。 各位,如果覺得 GIC
這個庫還可以,還希望能給個 star
,感謝! 。 專案地址
拋開原生應用不談,如果您想像前端開發一樣開發IOS應用,那麼我覺得 GIC
值得您一試。不管從開發效率、上手難度、程式碼可讀性等方面來說, GIC
都能有優秀的表現,而 GIC
目前相較於 flutter
等支援跨平臺的庫來說最大的缺點是不支援跨平臺。如果您開發的應用不考慮跨平臺開發的話,那麼 GIC
是一個很好的選擇。
有的朋友可能會說,現在flutter很流行,並且 dart
的效率比 JS
高。但是 GIC
在 UI
和 業務邏輯(ViewModel)
上是兩套完全不同的架構, UI
是純native的並且是基於 Texuture
開發的,而 ViewModel
你既可以使用 native
程式碼來寫,也支援使用 JS
來寫。另外在實際的應用(非遊戲)開發中,業務邏輯如果複雜到能通過不同的語言來區分的地步(比如dart和JS),那麼這樣的應用應該是一個非常複雜的應用了。因此我認為在語言上來比較孰優孰慮並不是最優先順序。另外,事實上 GIC
從架構設計上其實也可以支援 dart
語言、甚至其他的指令碼語言。