龔宇潔
方舟編譯器初探*
龔宇潔
(武漢城市職業學院,湖北 武漢 430070)
2019-04,華為首次公開了自主研發的方舟編譯器,2019-08-31開源編譯器框架代碼,從華為的設計思想和框架設計來看,方舟編譯器將會在業界帶來一場安卓性能革命。作為一名Android開發者,對方舟有限的資源和開源內容進行了學習和解讀,結合安卓編譯器發展的研究,對方舟編譯器進行了初步的探索。
方舟編譯器;Android;多語言設計;設計方案
2019-04,華為舉行了P30手機發布會,在展示手機產品的同時,首次公開了華為自主研發的方舟編譯器,稱之為“安卓性能革命”,能夠解決安卓程序“邊解釋邊執行”的低效,構級優化,顯著提升性能。系統操作流暢度提升24%,系統響應提升44%,三方應用操作流暢度提升60%,并將測試視頻進行了展示,同時承諾向業界開源。2019-08-31,華為方舟編譯器開源官網正式上線,開源編譯器框架代碼,包括編譯器IR(Intermediate Representation)、RC(Reference Counting)和多語言設計思想等,用于與行業、學術界交流和學習。雖然華為還沒有開源完整的方舟編譯器,但從華為的設計方案和框架設計來看,方舟編譯器確實能提升安卓應用程序的運行效率,這將會在業界帶來一場安卓性能革命。
對于編程常用的C/C++程序語言或Java程序語言,計算機識別不了,計算機只能識別和執行用“0”“1”這樣的二進制數所表示的指令,用二進制數表示的指令的集合稱之為機器語言。在計算機誕生初期,程序員在紙帶上打孔表示1,不打孔表示0,再將紙帶輸入計算機運算,但在現代無法實現。
匯編指令是匯編語言的主體。機器指令運用的是“0”“1”的組合,而匯編指令的格式更容易書寫和記憶,例如“MOV AX,BX”將寄存器BX的內容發送到AX上。匯編語言程序和硬件相關,不同的處理器匯編指令可能不同。程序員用匯編語言編寫程序比較復雜。
目前常用的C/C++、java等都是高級語言,高級語言從人類習慣的語言結構出發,更容易讀懂和表達,高級語言與指令或者硬件的相關度低,更多是對數據的運算和控制,通過算法實現具體功能。
高級語言程序需要通過編譯器變成匯編程序,然后通過匯編器變成機器代碼,最后才能被計算機執行。其中C/C++是編譯語言,靜態編譯,即編譯器直接將程序編譯成機器碼,安裝到硬件設備上就能執行。而Java為了實現跨平臺的操作,運用虛擬機來調度硬件資源,虛擬機中包含了翻譯器或編譯器,Java是預編譯語言,動態編譯,在開發環境中將源碼轉換成字節碼,再由虛擬機中的編譯器或解釋器轉換為機器語言。
Android應用程序基于Java語言,所以都是依靠虛擬機進行編譯或解釋的。2008年,Android1.0使用的是Dalvik的虛擬機,里面集成了一個解釋器,用戶每一次打開Android應用程序時,解釋器就開始翻譯。它的執行方式是一邊翻譯一邊執行,因此其執行效率很低。2010年發布的Android 2.2使用了JIT(Just in Time)即時編譯機制,即當Android應用程序運行時,會同時將用戶經常使用的功能編譯為機器能直接執行的機器碼,而不是碰到一句執行一句。當用戶使用了不常用的功能時,再讓解釋器進行翻譯。但缺點是不能一勞永逸,每次啟動應用程序都要重新編譯。2014年發布的Android 5.0,將Dalvik虛擬機換成了性能更好的ART(Android Run Time),同時把AOT (Ahead of Time)編譯器替代了JIT。AOT是指應用程序在手機安裝時就把代碼先編譯成機器碼,這樣就不需要每次打開應用程序的時候重新編譯。但其有2個缺點:①占用存儲空間,編譯后的機器碼體積迅速膨脹;②程序安裝速度慢。
對于2017年的Android 7.0,Google對其進行了改進,采用AOT+JIT+解釋執行的方式,應用程序安裝時不執行編譯,安裝速度快。應用之后,系統收集經常被傳輸的代碼信息,設備空閑時直接把這些代碼編譯為機器碼(AOT)。剩下的部分在運行時通過JIT和解釋器實現,用時間換效率,達到一種平衡。但無論如何演變,仍然只是在虛擬機上進行優化,虛擬機+編譯器+解釋器的結構本身就是一種對硬件資源的占用,Java這樣的預編譯解釋型語言,每執行一行代碼,先有解釋器解釋機器碼,然后再去執行。其優點是不同平臺只需要換用不同的解釋器;缺點是運行效率低下,程序的運行性能仍無法得到最大發揮。
Android編譯器演變如表1所示。
表1 Android編譯器演變
Android版本1.02.25.07.0 虛擬機DalvikDalvikARTART 編譯機制解釋器JIT+解釋器AOTAOT+ JIT+解釋器
Android 1.5系統之后Google允許Java通過JNI(Java Native Interface)Java原生接口去調用一些由C/C++代碼開發的so庫,來實現和C/C++等代碼的互交。兩種不同框架的語言相互調用,JNI需要調用硬件資源來做調度,這種機制效率也很低。
當內存資源不足時,C/C++需手動釋放內存,而Java可以自動釋放內存,Java虛擬機將會不定期自動回收不再被使用的對象,這也是Java語言的重要優點。但同時也造成了一些問題,當內存資源不夠時,虛擬機運用GC(Garbage Collection)機制進行內存資源回收,Java虛擬機所有運行的線程將會暫停。雖然這個過程很短暫,但用戶是無法準確控制的,如果是性能較差的手機可能還會出現“間歇性”卡頓的現象。
據官網介紹,方舟編譯器是為支持多種編程語言、多種芯片平臺的聯合編譯、運行而設計的統一編程平臺,包含編譯器、工具鏈、運行時等關鍵部件。從開源框架來看有以下特點。
方舟編譯器也屬于AOT,所采用的機制是在程序編譯打包的時候已經將Java代碼轉換成機器碼,將Java原本的動態編譯改為靜態編譯,這樣提供給用戶的安裝文件所包含就已經是機器碼了,不需要在用戶的手機上進行編譯,即使是應用程序安裝后首次運行也會非常流暢。
方舟編譯器將同時支持Java和C/C++多種語言,包括混合語言,各種語言實現統一的編譯器中間表示(IR),使各種程序語言代碼在開發者環境中編譯成統一的可直接執行的機器碼,具體如圖1所示。

圖1 多語言支持
方舟編譯器采用了引用計數法(RC,Reference Counting)來進行內存的實時回收,并且配合使用了專門的消除環算法(消除對象互相引用帶來的無法回收問題),來避免GC集中式回收帶來的系統卡頓。相比GC,方舟的內存回收是實時的而非集中式的,且不需要暫停應用進程,這樣便大大消除了卡頓。
方舟編譯器的工作原理:生成的安裝包改變了Android原本的apk格式規則,但有可能目前的Android是無法兼容的,但從官網的演示代碼來看,輸出了so庫,so庫是C/C++通過Android的 ndk編譯之后生成的本地庫,是Android系統支持的,形成so庫能夠保證最后生成的安裝包文件和原生的apk文件格式一致;虛擬機的自動回收內存資源的工作也不需啟動,“間歇性”卡頓現象消失。
從官方發布的內容看,方舟編譯器強大,始于安卓,強于安卓,趕超IOS,但是由于目前只開源的框架源碼和部分功能演示,所以方舟編譯器的具體表現如何還有待考證。既然方舟編譯器支持多語言和多種硬件平臺,是否會發布一個與AndroidStudio類似的開發平臺,也是值得期待的。中國計算機行業最根本的編譯器、操作系統、芯片等領域還是比較落后的,而華為是國內為數不多有這個能力,并且愿意投入人力和物力在這幾個領域的企業,華為需要的是時間,人們期待著方舟,期待著鴻蒙。
TP314
A
10.15913/j.cnki.kjycx.2019.23.018
2095-6835(2019)23-0047-02
龔宇潔(1984—),女,碩士研究生,研究方向為電子計算機。
2017年武漢市教育局教學研究項目“‘互聯網+’背景下《Android應用開發》課程學生自主學習策略研究”(編號:2017162)
〔編輯:張思楠〕