Flutter瘦身大作戰

背景

閒魚技術團隊於2018年上半年率先引入了Flutter技術做到客戶端開發,到目前為止成功改造並上線了複雜的商品詳情和發布業務。隨著改造業務的增多,安裝包體積急劇上增。安裝包體積決定了用戶等待下載的時間和可能會耗費的流量,如何控制安裝包體積,減小Flutter產物的大小成為當務之急。本文從閒魚客戶端項目實踐角度給出了一些通用的包大小檢測以及優化方案,希望為對Flutter感興趣的技術開發人員提供參考。

閒魚客戶端採用的Flutter和Native混合開發的模式,下面我們以ios端為例分析項目中Flutter產物的大小(ipa包瘦身需求更為急切)。

ios工程對Flutter有如下依賴:

  • Flutter.framework : Flutter庫和引擎

  • App.framework: dart業務源碼相關文件

  • Flutter Plugin:編譯出來的各種plugin的framework

  • flutter_assets:Flutter依賴的靜態資源,如字體,圖片等

第一次引入Flutter版本改造詳情頁後,ipa包大小增加近20M,其中包括Flutter引擎代碼+被改造業務代碼,繼續發布頁Flutter改造後,ipa增加4M+。進一步分析解壓ipa文件後發現Flutter.framework穩定保持在20M+的大小, 增加新的Flutter業務——發布頁之後,App.framework增幅近10M!

Flutter.framework是Flutter庫和引擎的代碼,我們能做的優化空間有限,先把目標放在dart業務相關的文件App.framework上。

Flutter產物大小分析

執行如下命令編譯出一個release模式下的App.framework,並使用 print-snapshot-si參數列印出產物具體大小

  1. flutter build aot --release --extra-gen-snapshot-options=--print-snapshot-sizes

結果如下:

  1. Building AOT snapshot in release mode (android-arm-release)...

  2. VMIsolate(CodeSize): 4660

  3. Isolate(CodeSize): 2585632

  4. ReadOnlyData(CodeSize): 2693576

  5. Instructions(CodeSize): 8064816

  6. Total(CodeSize): 13348684

  7. Built to build/aot/.

Instructions:代表AOT編譯後生成的二進制代碼大小。

ReadOnlyData:代表生成二進制代碼的元數據(例如PcDescriptor, StackMap,CodeSourceMap等)和字符串大小。

VMIsolate/Isolate:代表剩下的對象的大小總和(例如代碼中定義的常量和虛擬機特定元數據)。

具體到業務層,想要分析各個業務模塊所占用的大小該怎麼辦呢?

1.執行如下命令編譯出一個arm64架構的App.framework,並將它的包組成結構放到指定目錄build/aot.json文件中

  1. flutter --suppress-analytics build aot --output-dir=build/aot --target-platform=ios --target=lib/main.dart --release --ios-arch=arm64 --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--print_instructions_sizes_to=build/aot.json"

2.使用dart命令將上一步生成的aot.json文件轉化成結構可視化的網頁

  1. dart ./bin/run_binary_size_analysis.dart build/aot.json path_to_webpage_dir

runbinarysize_analysis.dart是dart提供的一個分析工具,在Flutter引擎源碼中路徑如下:

3.打開生成文件夾中的index.html即可分析具體業務所占用的大小,右上角的Large Symbols和Large Files按鈕可以直接定位體積占比從大到小的方法/文件

舉個例子,上面的分析顯示 PItemInfoInternal.fromJson方法占用了大量體積,跟蹤發現這個方法主要的操作是將Map數據轉化成對象

  1. PItemInfoInternal.fromJson(Map<dynamic, dynamic> map) {

  2. id = map['id'] as String;

  3. attributes = map['attributes'] as String;

  4. title = map['title'] as String;

  5. ......

  6. }

由此我們可以推斷這種類型轉換的操作會導致編譯生成一些體積很大的代碼。

優化措施

1.減少顯示類型轉換操作

按照上述分析發現顯示的類型轉換 asString/Bool/Int 這類操作會導致App.framework體積顯著增加,主要是它會增加類型檢查以及拋出異常的處理邏輯:

  1. if (x.classId < A && x.classId > B) throw "x is not subtype of String";

通過提取靜態公用方法的方式可以成功減少400k+體積。

2.通過編譯參數 --dwarf_stack_trace--obfuscate減小生成代碼的體積。

dwarf_stack_trace表示在生成的動態庫文件中,不使用堆棧跟蹤符號。

obfuscate表示混淆,通過減少變量名/方法名的方式減小代碼體積。

  1. //編譯release包並列印size

  2. flutter build aot --release --extra-gen-snapshot-options=--print-snapshot-sizes

  3. //--dwarf_stack_traces, -->減少6.2%大小

  4. flutter build aot --release --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes"

  5. //--obsfuscation, -->減少2.5%大小

  6. flutter build aot --release --extra-gen-snapshot-options="--dwarf_stack_traces,--print-snapshot-sizes,--obfuscate"

  7. //總大小減少8.7%

3.通過修改ios打包腳本xcode_backend.sh,刪除dSYM符號表信息文件,App.framework成功減小20%的大小。dSYM 是保存 16 進制函數地址映射信息的中轉文件,包含我們調試的 symbols,用來分析 crash report 文件,解析出正確的錯誤函數信息。

使用xcrun命令將dSYM從framework中剝離出來,可以大大減小App.framework的體積。

  1. RunCommand xcrun dsymutil -o "${build_dir}/aot/App.dSYM" "${app_framework}/App"

  2. RunCommand xcrun strip -x -S "${derived_dir}/App.framework/App"

4.減少Flutter和native資源重復造成的體積增大

利用橋接的方式,Flutter直接使用Platform端資源文件,避免因為資源文件重復導致的包大小增加問題。

主要方式是通過BasicMessageChannel在Flutter和Platform端傳遞信息。Flutter端將資源名AssetName傳遞給Platform端,Platform端接收到AssetName後,根據name定位到資源文件,並將該文件以二進制數據格式,通過BasicMessageChannel傳遞回Flutter端。

總結

引入Flutter帶來的安裝包體積問題會給很多技術團隊帶來困擾。通過以上措施,Flutter產物App.framework的大小減少30%+,閒魚技術團隊後續也會考慮採取下載並懶加載等方式減少資源占用的體積;繼續代碼生成中的各種對比,排查避免較大產物的寫法,同時也會和Google一起進一步尋找優化空間。

加入閒魚,一起玩些「酷」的

閒魚技術團隊是一只短小精悍的工程技術團隊。我們不僅關注於業務問題的有效解決,同時我們在推動打破技術棧分工限制(android/iOS/Html5/Server 編程模型和語言的統一)、計算機視覺技術在移動終端上的前沿實踐工作。作為閒魚技術團隊的軟件工程師,您有機會去展示您所有的才能和勇氣,在整個產品的演進和用戶問題解決中證明技術發展是改變生活方式的動力。

簡歷投遞:[email protected]

識別二維碼,前瞻技術盡在掌握

參考

  • https://github.com/flutter/flutter

  • https://github.com/flutter/engine

  • https://github.com/flutter/flutter/issues/21813

  • https://github.com/flutter/flutter/issues/20671

分享到Facebook

 


不知道如何找適合的對象?歡迎加官方LINE → Line ID:@shesay
戀愛小秘書免費一對一諮詢!
✔追蹤我的YouTube:https://www.youtube.com/@datenami
✔追蹤我的TikTok:https://www.tiktok.com/@datnami

 

配對成功的關鍵:參加實體交友活動

erose主題派對與戀愛小秘書創辦人娜米表示:「透過各種有趣的實體活動,不僅能親眼真實見到異性,也能在活動進行中讓大家很輕鬆自然的認識彼此、聊天互動,能更快速的找到適合的對象。」

結合大數據用心篩選 + 客製化條件配對

戀愛小秘書團隊已經成功替4000位以上的未婚男女配對成功,這個驚人成果背後的秘密在於「高度客製化服務」,跟每位客戶深度訪談,瞭解客戶真正的特質及需求,從「契合度」提高速配率。

訪談結果結合專屬的人格分析測驗與數據配對分析,精緻化的操作,締造高速配率!

除此之外,戀愛小秘書團隊還會定期追蹤客戶的後續狀況,目的是希望協助客戶發展長期且穩定的伴侶關係。

實名認證防造假!隱私保護最安心!

採用「實名認證」的制度,不僅是把關顧客的身份,避免已婚人士或動機不單純者的加入,更對客戶資料嚴格保密,讓客戶們能在安全且有隱私的狀況下認識另一半。

多元有趣的主題活動,豐富你的社交生活

戀愛小秘書團隊每個月都會規劃豐富多元的實體活動,從戶外踏青、娛樂遊戲、手作、料理課程到桌遊活動,希望客戶們能從歡樂的氣氛中認識彼此。

透過實體活動讓大家先有初步的接觸,然後再為會員們做「客製化」的約會安排。

另外針對想提升自身魅力的客戶,也有投資理財、形象穿搭等講座可供選擇。

追求脫單,先勇敢跨出你的第一步

許多單身者為了心中理想的對象條件,在還沒認識新朋友時,就先限制了自己。建議以認識新朋友的心態,積極參與活動,並適當的設限,才能真正為自己帶來戀愛的機會!勇敢跨出第一步吧!

♡ 現在就和戀愛小秘書娜米聊聊吧Line ID:@shesay

♡ 追蹤娜米的臉書粉絲團

她來報好康

 

SheSay 專注在 兩性、愛情等領域
建立專屬女生觀點的品牌形象
堅持「在第一時間掌握男女的時事議題」
將時下最流行的話題網羅、呈現。

馬上測算你的戀愛密碼

戀愛小秘書-娜米

單身很久?一直被分手?
從生日就看出你的戀愛疑難雜症!
娜米的戀愛數字密碼來幫你了。