9102年了,還不知道Android為什么卡?

2021-01-29    分類: 網站建設

導讀

最近華為方舟編譯器要開源了,筆者去看了下發(fā)布會PPT,發(fā)現作為一名Android開發(fā)者,PPT中所介紹的知識點我居然不能完全看懂?于是乎惡補了下PPT中的內容,整理成本文。

在開發(fā)階段Java源代碼在開發(fā)階段打包成.dex文件,C語言直接就是.so庫,因為C語言本身就是編譯語言。

在用戶手機中,APK中的.dex文件(字節(jié)碼)會被解釋為.oat文件(機器碼)運行在ART虛擬機中,.so庫則為計算機可以直接運行的二進制代碼(機器碼),兩份機器碼要互相調用肯定是有開銷的。

下面就來闡述下為什么兩份機器碼會不同。

這邊需要深入理解字節(jié)碼->機器碼的編譯過程,在圖上雖然都被編譯成了機器碼,都能被硬件直接調用,但是兩份機器碼的性能,效率,實現方式相差甚多,這主要是由以下兩個點造成的:

  • 編程語言不同導致編譯出的字節(jié)碼不同導致編譯出的機器碼不同。
  • 舉個例子,針對同樣是靜態(tài)語言的C和Java,對int a + b 的運算
  • C語言可以直接加載內存,在寄存器中計算,這是由于C語言是靜態(tài)語言,a和b是確定的int對象。

在Java中雖然定義對象我們也要明確的指出對象的類型,例如int a = 0,但是Java擁有動態(tài)性,Java擁有反射,代理,誰也不敢保證a在被調用時還是int類型,所以Java的編譯需要考慮上下文關系,即具體情況具體編譯。

所以連字節(jié)碼已經不同了,編譯出的機器碼肯定不同。

運行環(huán)境不同導致編譯出的機器碼不同

圖中明顯看到由Java編譯而來的機器碼包裹在ART中,ART全稱Android RunTime,即安卓運行環(huán)境,跟虛擬機差不多是一個意思。而C語言所在的運行環(huán)境不在ART中。

RunTime提供了基本的輸入輸出或是內存管理等支持,如果要在兩個不同的RunTime中互相調用,則必然有額外開銷。

舉個例子,由于Java有GC(垃圾回收機制),在Java中的一個對象地址不是固定的,有可能被GC挪動了。即在ART環(huán)境中跑的機器碼中的對象的地址不固定??墒荂語言哪管那么多幺蛾子,C就直接問Java要一個對象的地址,但萬一這個對象地址被挪動了,那就完蛋了。解決方案有兩個:

把這個對象在C里再拷一份。很明顯這造成了很大的開銷。

告訴ART,我要用這個對象了,GC這個對象的地址你不能動!你先一邊呆著去。這樣相對而言開銷倒是小了,但如果這個地址如果一直不能被回收的話,可能造成OOM。

(此處參考知乎@張鐸在華為公布的方舟編譯器到底對安卓軟件生態(tài)會有多大影響?中的回答)

3. 字節(jié)碼的編譯模板——未針對具體APP進行優(yōu)化

我們舉個例子來理解編譯模版,“Hello world”可以被翻譯為“你好,世界”,同樣也可以被翻譯為“世界,你好”,這個差別就是編譯模版不同導致的,

①. 統(tǒng)一的編譯模版(vm模版)

字節(jié)碼可以通過不同的編譯模版被編譯為機器碼,而編譯模版的不同將直接導致編譯完后的機器碼性能大相徑庭。

上圖的流程說明了在特殊情況下,AOT編譯實則不起作用,完全是靠解釋器和JIT在進行實時編譯,整個編譯方案退步到了Android2.2時期。

③. 聰明的ART

雖然這個問題存在,但并不是特別嚴重。因為ART并沒有我說的那么笨。在之后應用使用過程中,ART會記錄并學習用戶的使用習慣(保存熱點代碼),然后更新針對當前APP的定制化vm模版,不斷的補充熱點代碼,補充定制化模版。

這是不是聽起來很熟悉?在手機發(fā)布大會上的宣傳語“基于用戶操作習慣進行學習,APP打開速度不斷提高”的部分原理就是這個。

④. 最終大招,一勞永逸

其實要一勞永逸的解決這個問題思路也不難:我們只需要在吃飯前跟老板提前預定想吃啥就行,讓老板先準備起來,這樣等我們到了就不用等餐了。

在最新的Android9.0版本中,谷歌推出了這個類似提前預定的功能:編譯系統(tǒng)支持在具有藍圖編譯規(guī)則的原生 Android 模塊上使用 Clang 的配置文件引導優(yōu)化 (PGO)。

說人話:谷歌允許你在開發(fā)階段添加一個配置文件,這個配置文件內可指定“熱點代碼”,當應用安裝完后,ART在后臺悄悄編譯APP時,會優(yōu)先編譯配置文件中指定的“熱點代碼”。

雖然谷歌支持,但是這塊技術對于APP開發(fā)人員而言國內資料過于缺乏,普及面不廣。筆者先貼上官方鏈接,以及這篇博客,其中介紹的還是挺詳細的。(隔壁Xcode針對PGO都有UI界面了)

三、解決思路

解決思路總結為四個字就是:華為方舟。

方舟的解決思路:

  1. 針對虛擬機問題,方舟說:我不要你這個爛虛擬機了,我們裸奔
  2. 針對JNI調用問題,方舟說:我們讓Java在編譯階段跟C一樣直接編譯成機器碼,干掉虛擬機,跟.so庫直接調用,毫無JNI開銷問題
  3. 針對編譯模版問題,方舟說:我們支持針對不同APP進行不同的編譯優(yōu)化

總結一下:方舟支持在打包編譯階段針對不同APP進行不同的編譯優(yōu)化,然后直接打包成機器碼.apk(很可能已經不叫apk了),然后直接運行。

這樣看起來方舟確實解決掉了三大問題,但是,代價呢?

如果按照這個思路,方舟就肯定不止是一個編譯器了,它應該還有一套自己的runtime。當然這些都是后話了。

關于方舟的實現只是大概講了思路,但沒有深入,因為一來方舟沒開源,二來方舟發(fā)布會PPT營銷層面更多,技術細節(jié)缺少,現在奇思妙想完全是紙上談兵,一切還是靜待開源吧。

本文標題:9102年了,還不知道Android為什么卡?
分享URL:http://www.bm7419.com/news46/98096.html

成都網站建設公司_創(chuàng)新互聯,為您提供標簽優(yōu)化、建站公司軟件開發(fā)、服務器托管營銷型網站建設、網站導航

廣告

聲明:本網站發(fā)布的內容(圖片、視頻和文字)以用戶投稿、用戶轉載內容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網站立場,如需處理請聯系客服。電話:028-86922220;郵箱:631063699@qq.com。內容未經允許不得轉載,或轉載時需注明來源: 創(chuàng)新互聯

網站優(yōu)化排名