華為方舟編譯器遠沒有你想像的那麼簡單
在華為P30系列的國行發布會上,華為用幾頁PPT引出了「華為方舟編譯器」這個神奇的新東西,華為將其稱作是「Android的性能革命」,並大方地將其開源,希望App的開發者們都能用到它。
這項技術已經被華為納入了EMUI9.1,能夠升級到EMUI9.1的用戶都可以享受到它帶來的性能提升。網路上已經有不少的網友用正常版本的微博和方舟編譯器編譯的微博進行了對比,二者的啟動速度、滑動的跟手性等都有明顯的區別。
在進行今天的文章前,筆者先和大家普及一下現有Android應用運行的工作機制、原理。
Android所有的應用在編譯打包的時候實際上是都打包成了位元組碼,而我們的手機CPU並不認識位元組碼,它們只認識機器碼。於是我們需要在App和CPU之間添加一位「翻譯」,App才能夠正常執行。
這和一些Java應用需要通過JVM執行類似,在Android中,App需要依賴Dalvik才能執行。
在Android4.x時代,系統都採用的動態解釋執行+JIT這一套方案來執行App,即App的位元組碼會在運行時由Dalvik虛擬機直接解釋成機器碼執行,或通過JIT即時編譯成機器碼執行。
這是典型的「邊解釋邊執行」模式,華為在發布華為方舟編譯器的時候也提到了這點。
Android5.x開始,Google對App的執行模式進行了優化,引入ART取代古老的、緩慢的Dalvik。
ART在進入Android之初自帶了一個AOT(AheadofTime)編譯器,這個編譯器將會在App安裝的過程中直接將所有的Dex位元組碼編譯成機器碼,之後App每次執行都執行的是機器碼,而不是位元組碼。
由於App執行的過程中省去了中間的「翻譯」,所以其執行效率自然是更高的。這是Android5.x到6.x在使用的方式,從描述上來看,它和華為方舟編譯器是很類似的,即所有的代碼都預先編譯成機器碼,App在運行時直接運行機器碼,省去中間的轉換過程,提升執行效率。
這個方法確實是高效的,能顯著提升性能,但是它卻有兩個致命的缺點,一個是慢,一個是大。
完全AOT編譯是在App安裝的過程中進行的,這會使得App的安裝過程變得相當慢,碰到淘寶這種大型的、邏輯複雜的App,其安裝速度會慢到令人髮指。
如果你有使用過那個年代的Android手機,你會發現系統每次更新後會在第一次開機的時候出現「Android正在升級,正在優化應用」,這實際上就是Android5.x的機制引起的,即所有的系統應用在第一次開機時都會被預編譯成機器碼,以提升系統的整體性能。
如果恰好你在那個年代用的Android手機性能很一般,例如搭載的處理器是聯發科的中低端處理器,有的時候這個優化需要跑半個小時及以上,非常地煩人。
所以在後續的Android中這樣的機制被捨棄了。
至於「大」這個缺陷,它在Android5.x的年代是體現得更加嚴重,因為當時大量的手機快閃記憶體都是16GB、32GB。App的位元組碼都轉成機器碼會讓一個App的體積急劇膨脹,這會使得應用更加吃用戶的存儲空間。
在那個年代你可能會經常遇到「手機沒裝幾個應用空間就不夠了」的情況,這也和當時的Android對App的處理有關。
從Android7.x開始,所有的App改為了「混合執行」的模式。在日常生活中我們使用App可能只會很頻繁地用到其個別的功能,很多功能平時並不是常用的。
在你使用App的過程中,Android會跟蹤你的使用情況,它會記錄下你使用過程中App經常運行的代碼塊,並將其編譯成機器碼,其餘部分則採用老套的「邊解釋邊執行」的方式去運行。
這很好地解決了App安裝速度很慢、安裝後體積龐大的問題,但相較於Android5.x時代的方法,這樣的「混合執行」是要犧牲一些性能的,屬於一個折中的、平衡的方案。
Google仍然在持續優化這一套方案,在Android8.0上他們對解釋器進行了大概,提升了App的執行效率,在即將到來的Android10.0上,他們還會向開發者提供「預置熱點代碼」的功能,這樣一來在應用安裝好後,系統就會將一部分代碼預先編譯成機器碼,提升應用的運行效率。
然而雖然Google這麼做確實可以進一步優化混合執行的效率,但混合執行永遠不可能達到將App預編譯、只執行機器碼那麼高的效率。
華為方舟編譯器強調的就是「只跑機器碼」,而且是「全程都只跑機器碼」。
這意味著從應用安裝後,應用跑的就是機器碼,這和Android5.x時代Google的做法是一樣的。
那麼問題就來了,華為的方舟編譯器究竟只是一個類似AndroidRuntime的東西,在App安裝的時候對App進行編譯,還是一個比它還要高端的東西呢?
在發布會上,華為提到了一個細節,他們表示這個編譯器是給 App 開發者提供的,這意味著這個編譯器本質上並不是一個內置在手機系統里的東西,而是一個給開發者使用的工具,或者說工具鏈。
綜合華為之前在自己開發OS的新聞,方舟編譯器甚至有可能是華為自研OS的一部分,它的存在能夠讓應用開發者輕鬆地將現有的Android工程編譯成適合華為寫的Runtime的應用,進而能夠兼容地運行在華為自己的OS上。
華為之所以創造這個方舟編譯器,很有可能不只是為了提升Android的性能那麼簡單。
華為方舟編譯器有兩個點能夠大幅度提升Android的性能,第一個是它是一個面向開發者的工具,這意味著它編譯的是開發者編寫的工程,從源代碼直接編譯成機器碼,將二進位打包到APK中。
這是一個相當有趣的思路,方舟編譯器是在開發者的電腦上完成的編譯這個操作,這意味著編譯和用戶以及用戶的手機沒有任何關係,在開發者的電腦上,華為可以將這個編譯的優化做到極致,編譯出儘可能高效、簡潔的機器碼,同時避免了App安裝時間長和App體積過大的問題。
另一點是華為在編譯器中加入了和OS的交互,不過這可能只能在EMUI上實現。在編譯的過程中,編譯器會在編譯時對一些特別的代碼進行標記,例如IO密集的代碼等等。系統在執行它的過程中看到了這些標記,就會預先對系統資源進行調配,這和GPUTurbo是差不多的思路。
這麼一來,應用的執行將會變得非常通暢,進而總體的性能會有一個大幅的提升。
如果華為真的已經在EMUI中加入了一套配合方舟編譯器做的自己的Runtime,那麼即使華為開源了這個編譯器,那麼開發者也只能給EMUI編譯更快的應用,其他廠商是偷不走這個技術的。
從華為開源它的動作來看,筆者個人認為華為應該是做了一套自己的Runtime實現,配合這套Runtime,經過方舟編譯器編譯出來的App在性能表現上才會有大幅提升。它可以兼容其他廠商的手機,但是性能表現是會打折扣的。
由於華為只開源了編譯器這個部分,所以其他廠商根本沒有辦法復刻華為通過方舟編譯器給App運行性能帶來的提升,因為其他的廠商根本沒有辦法通過這個編譯器反推出Runtime。在這個點上,華為牢牢地限制住了競爭對手。
華為的這個舉動可以說是在對Android生態做進一步的分裂,華為最近是動了EMUI底層方面的東西,不知道華為是不是已經開始在向自己的OS過度了,如果是的話,這一次開放方舟編譯器將會是一個關鍵的節點。