開源|Zucker:Android APP模塊化大小自動分析統計工具

開源項目專題系列

(四)

1.開源項目名稱:Zucker

2.github地址:

https://github.com/wuba/Zucker

3.簡介:Zucker是基於APP模塊的,一個簡單無侵害計算AAR獨有大小的工具。


APP模塊化大小自動分析工具是用來解構Apk大小構成的一種分析方式,它可以在不侵入用戶代碼的情況下,自動分析出當前項目的構建方式、依賴結構,通過計算獨有依賴的大小從而精準的計算出一個模塊在Apk中所佔的大小。

Zucker於2020年3月份開源,它在行業內的特點如下:

  • 首款從代碼結構模塊化分析統計Apk大小的工具;
  • 利用用戶自身的運行環境即可運行,具有一定的通用性;
  • 使用腳本即可實現,無需入侵用戶代碼,靈活性高、擴展性強;
  • 對比原有的統計方法,通過自動化,實現提效;
  • 控制Apk大小的措施工作左移,在集成階段,甚至在更早的需求開發階段發現問題,把控APP的質量風險;


為什麼要使用Zucker

一款Android APP,應用市場的評分是用戶衡量下載意願的關鍵參考標準,絕大部分用戶會在同類產品中願意優先選擇評分較高的APP。然而,調查顯示:APP評分越高,用戶下載量越高;APP安裝包體積越小,用戶下載量越高。那麼,如何有效的控制APP安裝包體積也是提高用戶下載意願的措施。下圖是58APP近兩年來的版本變化:

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖一 58APP大小變化趨勢

業界內的有很多人都致力於研究在當前的APP狀態下,對其進行縮減優化,效果也很顯著,典型的有:使用TinyPNG或者WebP優化圖片資源、使用lint對於無用代碼進行檢測、AndResGuard、7Zip壓縮等等。我們發現,業界的普遍解決思路:在既有的APP上想辦法縮減。

那麼有沒有什麼方法,是可以在APP正式產出之前,就能對其監控呢?業內的一個典型的案例:大圖片檢測。對整個Apk進行解析,將圖片資源按大小進行排序,找到前50個大圖片,再使用TinyPNG或者WebP等優化手段。但是,仔細想一下,這個圖片來源於哪個需求?這個需求來源於哪個模塊?這個模塊現在在Apk中的佔比是多少?所以,僅僅從拆解Apk的角度去分析還遠遠不夠。

我們知道,導致APP增大的最直接因素是需求的迭代,在現有的需求開發中,一個需求可能涉及到一個或者多個模塊,比如:各個業務線,又或者是登錄、認證、微聊、視頻、定位等模塊。假如認證模塊引入了一個導致APP增大5MB的第三方庫,當我們嘗試使用業內普通的解決思路時,對其優化可能收效甚微。但是使用Zucker,由於它對於認證模塊進行監控,它可以在該需求正式被打包進APP之前發出警告。從根源監控,將這個5M的第三方庫用其他更小的庫替代或者通過自實現的方式,都可以減少它的大小。

針對這個問題,我們也嘗試了很多種辦法,我們現在已經有基於需求層面來分析Apk的組成,它已經在58APP服役兩年多的時間,監控了近30多個版本,反響非常好。

現在我們更進一步,利用模塊化的思路,把Apk的統計分析工作進一步完善,將控制Apk大小的措施工作左移,在集成階段,甚至更早的需求開發階段提早發現代碼質量問題,從而更好地保證APP的質量。


整體架構

Apk依賴的模塊目前大多是由AAR組成,統計Apk中模塊的大小本質上是在統計AAR的大小。由於Apk在打包過程中,會利用AIDL和AAPT進行代碼、資源壓縮、混淆等操作,所以,只計算AAR的大小是不準確的,實際上需要統計的是AAR在Apk中進行壓縮、混淆之後的實際大小。此外,一個模塊可以包含多個AAR,這時候需要對整個APP的依賴關係進行分析,從而找到目標AAR的獨有依賴關係。最後,為了實現模塊的自動分析統計,我們利用Python實現了對於項目工程輕量級、微侵入的統計方式。

Zucker的整體架構劃分如下:自動化打包統計、依賴分析、目標AAR模擬:

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖二 Zucker項目整體架構


自動化打包統計

對一個給定的目標工程避免產生侵害和改動,需要對源碼工程做拷貝處理,然後利用該拷貝的工程計算依賴關係推理出獨有依賴。再克隆一個工程用於替換獨有依賴的目標AAR,再對克隆工程進行打包。最後,通過打出的兩個克隆工程的包的大小差值,可以得到目標AAR的大小。


1. 克隆工程

為了實現無侵害計算,需要修改工程的gradle腳本來實現自動模擬AAR以及計算包大小,將原有工程進行克隆再分析模擬AAR及打包統計。使用Python腳本文件需要放置目標工程的同級目錄,運行腳本在同級目錄產生一個output目錄,統一存放拷貝的工程文件。

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖三 工程克隆

2. 編譯過程

整個編譯過程包括以下步驟:初始化工程→自動尋路查找工程入口→清除flavors→插入計算腳本→執行打包命令。通過此流程,可完整實現自動化尋路APP入口並修改配置來實現基礎包打包和計算包體積大小任務。

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖四 打包編譯過程分析

依賴分析

在上文中提到獲取用戶輸入的AAR,分析工程中各模塊依賴關係。獲取AAR的相互依賴關係,對於計算AAR大小起到關鍵作用。首先明確兩個依賴關係概念。

  • 獨有依賴:對於某一AAR,內部引用庫僅被當前AAR所依賴,再無其他依賴關係,則這個庫被稱為AAR的獨有依賴。
  • 公有依賴庫:不同於獨有依賴,一個庫可能被多個AAR所引用,則這個庫被稱為公有依賴。

回到上面說的,若要統計AAR在APP包大小中的佔比,除了它自己還不夠,還要分析該AAR的獨有依賴才能正確計算引入該AAR後的大小。


1. 依賴樹轉化

在項目的Gradle文件中可以找到該項目的依賴引用,項目執行./gradlew dependencies命令後會獲取當前項目的依賴樹結構,為了方便處理,將項目中的依賴庫簡化成A,B,C來表示,如圖所示,A,A1,A2表示項目直接引用的AAR依賴。B,C是A的子依賴,同時C,D是A1的子依賴。根據上文所述,A的內部依賴B沒有其他的被依賴關係,因此稱B為A的獨有依賴。另外的由於C同時被A和A1依賴,因此稱C為公有依賴。

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖五 依賴關係分析

理解依賴樹結構特點,可將依賴樹形結構轉化成列表來顯示。由上述分析可知一個依賴庫可能被多個庫依賴,產生依賴關係。同時依賴關係是單向有序的,箭頭指向表示A依賴B:A是B的父依賴,B是A的子依賴。現挑出A,A1,C作為例子分析,將A,A1作為一個父節點,節點內部同時維護兩個列表,父節點列表(parents)和子節點列表(children)。依次就可以將依賴樹中所有的依賴關係放置在節點類型的數據結構中。另外root節點是工程總節點,它是A,A1和A2的父節點。通過此步驟,得到依賴列表,記錄工程中所有依賴節點:

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖六 依賴關係處理


2. 獨有依賴分析

統計目標AAR大小時,不僅要統計目標AAR還要包括它的獨有依賴。通過上文步驟獲取到了項目所有AAR列表,在輸入目標依賴名稱後,我們在列表中遍歷找到該目標,檢查其子依賴然後獲取最後的獨有依賴,檢查流程如下:

  1. 羅列目標依賴下的所有子依賴,並且遍歷子依賴的子依賴,將它們記錄到新列表中;
  2. 採用深度便算法來逐一去判斷新列表中的依賴,判斷其父依賴是否僅在該列表中,如果父依賴全部都在該列表中則保留,否則從列表中可刪除該依賴;
  3. 經過步驟2後的篩選,剩下的節點則為目標依賴的獨有依賴。

下面我們以上文圖中的節點A1為例,將A1節點所有的子節點記錄到列表。首先獨有依賴包括它自身,故A1保留。C節點的父父節點有A和A1,A不在當前列表中,因此C不是獨有依賴,將C移除。D的父節點僅有A1且在列表中,因此D是獨有依賴。以此類推,在判斷I節點時,由於C節點已被移除不在列表中,因此I也不是A1的獨有依賴。節點獨有依賴尋找流程:

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖七 獨有依賴的獲取


目標AAR模擬

在項目打包生成Apk過程中,會利用Gradle緩存特性,工程編譯前,獲取用戶輸入的目標AAR,腳本通過目標AAR名稱在緩存目錄下自動尋找。然後將本地的目標AAR文件進行模擬處理,打包時將該模擬後的AAR打入Apk中。模擬替換目標AAR流程:

開源|Zucker:Android APP模塊化大小自動分析統計工具

圖八 目標AAR的模擬

我們知道AAR是二進制歸檔文件,也是壓縮文件,只不過它是AAPT打包命令中的一個結果,通常會壓縮:資源文件、類文件、系統文件等。所以找到該AAR後,我們進行“解剖”,步驟如下:

  1. 將目標AAR在當前目錄下備份一份;
  2. 將AAR文件重命名變成.zip文件並進行解壓縮;
  3. 遍歷解壓縮文件目錄,當目標是文件時,判斷其文件類型是否為.xml或.9.png,是則跳過;否則,將其文件大小置為0KB;
  4. 解壓縮文件完全按照步驟3處理完成後,將其重新壓縮為一個模擬的AAR文件,參與打包計算;
  5. 打包完成後,為了不影響後續打包任務,刪除模擬的AAR將備份的AAR文件恢復;

修改build.gradle文件,使用Gradle的打包特性配置所有all*.exclude移除對應的group和module;

未來規劃

目前已使用zucker統計了最近三個版本的模塊大小,統計耗時已大幅度減少。基於上述流程可以快速完成統計目標AAR及其獨有依賴在Apk包體積大小佔比,接下來還有些方面亟需提高。

  1. AAR大小列表展示,基於圖表形式展示,一目瞭然;
  2. 版本具體需求功能結合展示,並形成相關性文檔;

如何貢獻&問題反饋

本次開源只是Zucker貢獻社區的一小步,我們誠摯地希望開發者向我們提出寶貴的意見和建議。您可以使用如下方式向我們反饋建議和問題:

在https://github.com/wuba/Zucker提PR或者Issue。


胡昊,Android資深開發工程師-負責Zucker項目整體架構、技術選型,主要參與目標AAR的模擬替換;

曾鵬,Android資深開發工程師-負責Zucker項目工程自動化打包統計;

李賀,Android高級開發工程師-負責Zucker項目中依賴關係轉化與Gradle緩存處理;

楊文蛟,Android高級開發工程師-負責Zucker項目數據統計與調優;


與項目成員零距離交流?

一切應有盡有


開源|Zucker:Android APP模塊化大小自動分析統計工具

微信號 : jishu-58 添加小秘書微信後由小秘書拉您進項目交流群


分享到:


相關文章: