Android卡頓千古謎案全面解析
有沒有感覺你用的Android手機很卡?貌似手機配置都已經挺不錯的了,四核、八核、≥2GB RAM這樣的配置居然還會發生動畫掉幀、點擊某個按鈕或圖標出現停頓一會兒之類的情況?高通、MTK、英偉達之類的芯片制造商不是整天宣稱什么制程、架構 如何先進,什么一秒鐘多少萬多少億次浮點運算,怎么還整天被iPhone用戶嘲笑很卡很不爽?
本文引用地址:http://www.j9360.com/article/277680.htm
關于Android系統存在卡頓和不流暢的問題,似乎是個千古謎案——即便到現在也還有很多Android用戶堅持說他們新買的旗艦已如絲般柔滑,卻真正在流暢的細微處比iOS差了一截。不過從古到今,試圖解釋Android卡頓的觀點就有千百種,據說即便是采訪Android內部開發工程師,他們也說這是個說不清道不明的問題。這次我們就從相關Android卡頓的幾個主流說法談起,嘗試從相對淺顯的角度來理解這一問題。
都是Dalvik VM虛擬機惹的禍?
按照普通人對虛擬機的理解,就是平常一直在用Windows操作系統,想裝個Mac OS玩玩又沒錢買蘋果電腦咋辦?——裝個虛擬機。從這個角度來理解,不管是出于玩機還是開發、或考慮兼容性的問題,用過虛擬機的同學就知道,這東西的效率 和原生安裝方式不在一個層面,不管是從驅動、資源利用等各角度來看都是如此。

Android的系統框架上,在最底層的Linux內核之上就跑了個虛擬機,在Android 4.4之前,這個虛擬機叫Dalvik VM。絕大部分Android應用就運轉在Dalvik VM虛擬機之上——很多人,甚至是程序員認為,Android系統之所以不流暢和卡頓,罪魁禍首就是此虛擬機,想想我們平常應用層面虛擬機的運行效率就知 道了,再牛逼的硬件也抵不住軟件這么坑啊。
早年的Android系統能有如此奇葩的框架和執行思路并不是因為Andy Rubin真的很二。Android選擇這條路的原因是看中互聯網上浩瀚的Java資源——Java應用可以運行在Android這種Linux內核的系 統上正是拜虛擬機所賜,對于一個當時的新生系統而言,想要盡早構建起應用生態,這是個捷徑——也是Android現在擁有這么多應用資源的關鍵所在(雖然 蘋果就沒這么做)。
不過另有一個幫派的程序員表示,這個層面的虛擬機和我們平常自己在電腦上裝的虛擬機根本不是一回事,它的執行效率并沒有人們想象的不堪,實際使用中和直接調用底層基礎函數也沒差多少。

(NDK的也可是讓Android應用不用跑在虛擬機上)
我們從谷歌后來的行動看到,情況好像沒有這么簡單。早在Android 2.3時期,谷歌就意識到Dalvik并非長久之計,就為Android引入了NDK——這是個真正的開發包,使用C/C++語言也可以為Android 開發應用,以這種方式開發的應用不會跑在虛擬機上。彼時的程序員認為,這是Android從應用層真正開始具備與iOS相抗衡實力的開始,但這種夢想很快 就被打破,一方面是讓開發者放棄Java全面轉向C/C++并不現實,而且后兩者開發難度甚高,涉及內存操作甚至與設備驅動程序對話,對于Android 這種機器種類繁多的系統而言,開發者采用NDK很不現實(類似《極品飛車》這種大型3D游戲運行代碼理應采用C++,所以這類游戲針對Android手機 的不同處理器甚至還有不同的版本)。
所以在Android 4.4時期,谷歌為之引入了一種新的ART虛擬機,用以替代Dalvik。ART的特點是相比Dalvik更為高效:Dalvik虛擬機在每次運行應用時 會將之編譯為二進制機器代碼,ART的改進之一就在于在應用安裝的時候就將二進制代碼編譯完成(所以每個應用安裝所占空間會更大),這叫預編譯模式,而不 是等到每次運行應用才編譯。

理論上聽來,ART似乎的確較Dalvik效率更高些,谷歌自己說ART對比Dalvik速度平均提升幅度達到80%,不過各位已經在用 Android 4.4甚至5.0的小伙伴有這種體會嗎?或許今后隨著Android生態以及系統自身的完善,ART可以表現出更大的優勢,起碼現在我們沒怎么看出來它對 系統流暢性體驗改善有多大貢獻。
另外,在系統框架層面,除了探討虛擬機可能是拖垮Android流暢性的元兇之一這種說法,還有人也會談到Linux這類宏內核在驅動方面的先天不足,這些或許都是阻礙Android有絲般流暢的要素,但是否還有其他原因呢?
硬件加速弱爆了
顯示系統圖形界面的時候,如果畫圖的工作都交給CPU完成,這效率是可想而知的,猶如你讓一位精通數學的同學畫圖,多少他倒是能畫,只是能不能畫好 很成問題。如果GPU,也就是專門的畫圖工作者能夠協助這個過程,情況自是大不相同。雖說系統流暢性是個相當大的話題,但硬件加速是否做得好就成為其中的 重要因素。

完善如上所述的這個過程,幾乎是貫穿Android 2.x早期,到最新的Android 5.1,甚至此后很長一段時間內,谷歌需要努力的方向。針對系統圖片、網頁等2D圖形繪制,Android所用的是谷歌早在2005年就收購的 Skia(那時Android都還沒出生,Chrome也采用Skia作為2D圖形引擎)。
Skia原始版本的圖形光柵處理完全基于CPU和軟件運算,也就是說早期Android的2D圖形繪制對GPU的利用率存在嚴重不足,相較iOS和Windows Phone這種在硬件加速領域有著很久積累的系統完全不是一個水平。

在Android的系統設置-調試選項中,有個“強制進行GPU渲染”選項,開啟這個選項以后會發現某些應用的運行的確更流暢了,但有些則出現了更 糟糕的使用體驗。在Android 2.3時代,國外科技博客DorothyBrowse特別強制開啟這種Skia GPU加速,嘗試進行Webkit渲染(Chrome的渲染引擎)測試,結果發現相較CPU自己畫圖,所謂的GPU加速居然出現了反效果,可知當時的 Skia GPU加速在Android平臺有多么不成熟。
在Android 3.0之前,這套系統都沒有真正行之有效的圖形加速方案(即便從初版開始,Android就在努力融合硬件加速),Android 3.0才實現窗口相對完整的硬件加速繪制。實際上,即便是到Android 4.1,谷歌大肆宣傳的黃油計劃,過渡動畫幀率達到60fps,通過預判和緩沖來提升效率,其GPU加速支持也并不完整。谷歌自己的官方文檔中就提到,并 不是所有2D圖像操作的API都已經支持硬件加速。

不過總的說來,Android的GPU加速是朝著逐步完善的方向發展的,最新版相較過去已經有了很大程度的提升,從系統級應用和各類操作這些年來流 暢度的明確提升就能感覺得到,即便這種提升在iOS和Windows Phone面前還是顯得有些無力。可是來到第三方應用,這個問題又變得非常復雜。
第三方應用質量很悲劇
在宣稱如“絲般順滑”、甚至“趕超iOS”的Android 4.1問世以后,不說和iOS比實際如何,其系統級應用倒真的流暢了很多,可是第三方應用死性未改,該怎么卡還是怎么卡。這就是個相當復雜的問題了。
其一,在Android一步步向前的步伐中,API Level越高,GPU硬件加速也的確愈加完善,比如Android 5.1所用API Level 22。所謂的API Level,標識的是Android平臺框架的API版本。這個API可以理解為Android所跑虛擬機針對應用開發而支持的功能,隨著版本號的變化, 這些“功能”在發生著升級或轉變。對Android的系統應用而言,采用最新的API是理所當然的,流暢性也保持在最佳狀態。

但對第三方應用來說,采用最新的API,就意味著對舊版本系統的拋棄。比如微信應用更新,如果很任性地用上API Level 22,那么最新版的微信將只支持Android 5.1,人類可以忍受嗎?所以微信迄今為止還在采用API Level 9,微博則為API Level 14。這種API的迭代,也是蘋果為何高度追求系統一致性的重要原因。想想Android系統的碎片化問題,第三方應用要變得更高效,好像是個根本無法完 成的任務。
這還只是第三方應用開發的一環。其二,Android應用開發者的“隨性”讓Android應用的效率更加悲慘。比如說谷歌在應用開發的指導原則中提到,如果應用不夠流暢,應該看看是否存在“過度渲染(OverDraw)”的問題,就是布局重疊、重復繪制。


要檢查這個問題,有興趣的同學可以一起來做這個實驗。在Android系統設置的開發者選項中,選擇“顯示GPU過度繪制”,此時整個界面變得花花 綠綠一片。這些色塊所表達的是,無色透明狀態為最佳,藍色表示很好,綠色為不錯,淺紅色表示較差,深紅色為過度繪制問題嚴重。類似Instagram等應 用的情況似乎挺好,而某博和Facebook過度渲染的問題就很嚴重。這只是Android應用開發中的一個例子,如此這般罔顧開發原則的狀況那是數也數 不清的。在Android相對開放的應用世界中,這種情況是不會有警察去抓的,顯然iOS全程把關App Store就不會這么悲劇。
其三,在天朝這樣一個奇特的國度,開放的系統無疑為許多應用開發商提供了大好機會。很多應用當安裝到你手機中,其行為習慣可能是你完全不知道了,而且可能實情會更令你震驚,這就是下面一個話題了。
內存居然還不夠用?裝越多APP手機越卡
相關Android裝越多應用,手機越卡的解釋非常多樣,甚至包括對于固態存儲原理的解釋。或許這些都是原因所在,不過更關鍵的原因是這樣 的:Android系統中有個叫做Receiver(接收器?)的東西,負責傳遞系統接收到的變化,就像是神經系統。比如說按下Power鍵鎖屏,長按關 機,或者長按相機按鍵啟動相機應用,或者插入耳機,都是在Receiver接收到以后通知相應apk,后由程序給出響應。

應用本身就可以跟系統注冊任何形式的Receiver,其較大的用處之一是通知系統啟動某個程序。比如YouTube的Receiver在開機時、 系統語言切換后、系統賬戶改變后這三種情況下自動啟動YouTube應用本身——這是個比較常見的Receiver。而國內的諸多“異士”是如何寫 Receiver的呢?
某些著名視頻站APP在下面這些情況下都會啟動,包含開機時、網絡狀況改變時(2G、3G與WiFi間切換)、安裝其它App時、卸載其它APP 時、用戶喚醒機器時.。。對于用戶而言,無論你怎么殺進程清內存,只要這些操作被觸發,Receiver就會啟動相應程序,話說連個WiFi、下個新應用 都要啟動該應用,哪有透明度可言,真是獨有社會主義特色。

此類國產APP相當多見,常見Receiver動作還有:耳機拔出或插入時、文件下載完成后、WiFi掃描SSID完成后,都啟動程序,是不是感覺 灰常神奇?它們的宗旨就是永遠不會被你殺死,什么一鍵殺進程,分分鐘給你活過來,除非徹底卸載它們,或禁用相應Reciever。在這種情況 下,Android系統對于內存容量的要求自然是非一般的。
所謂的內存回收機制此刻都已不值一提,何以iPhone 1GB內存流暢運行至今,而Android現如今已是3GB時代;這也是很多Android優化文章告訴用戶,如果某應用一周不用就卸載的核心所在,環境使然。你聽說過iOS優化讓用戶卸應用的嗎?

碎片化問題讓Android千瘡百孔
可以說,除了Android本身的頑疾之外,導致上述絕大部分問題的根源就是Android的碎片化,無論是Android自身開放的態度讓各種高 配、低配的手機都在使用,還是手機制造商對Android進行的二次開發。要將硬件加速做好、規范第三方應用質量,在Android開放的理念下是幾近不 可能完成的任務,且谷歌自己都難以收拾局面。

Android的開放和碎片化帶來的問題還遠不止上面這些,一個典型的例子是iOS和Windows Phone都具備了特別出色的信息推送機制,比如說QQ、微信接收消息,在iOS和Windows Phone中,應用本身不需要常駐后臺,通過每臺手機和推送服務器保持唯一連接,就能收到推送通知,無論對性能和功耗的節省都具備了極大的意義。
Android系統當然也具備了消息推送的可行性,但由于碎片化問題,以及國內因為某種原因不得不去掉谷歌服務的現狀,令Android不同應用采 用五花八門的推送機制。許多Android應用獲取消息的方式是輪詢(而非推送),即應用主動地與服務器連接并查詢是否有新消息,可想而知它對系統和網絡 資源的消耗。

關乎Android系統本身,則除了文首提到的虛擬機機制,還有許多相當微妙的問題形成它與iOS之間的流暢性差異,比如Android對多任務的 支持更類似于桌面系統,本身就只有靠堆砌硬件才能滿足這種多任務的需求,當然iOS的多任務也已經不像很多人理解的那樣,是多年前的“假后臺”了,它針對 第三方應用開放的多任務API正越來越多。
總之,Android的卡頓和不流暢是個極其復雜、龐大的問題,上面所提的這些也只是挖掘了其中的一部分。就Android系統的發展軌跡來看,從 初代問世至今,其發展史都可以看做是谷歌在系統流暢性問題上所做的一次次努力,流暢性改善甚至是Android前行的一條線索,所以谷歌也才毫不吝嗇地一 次次地宣傳,我們的系統更流暢了,不管相較競爭對手有多大差距和多少不可控性,現在的Android也已經比過去流暢了很多,雖然未來還有很長的路要走。
linux操作系統文章專題:linux操作系統詳解(linux不再難懂)
可控硅相關文章:可控硅工作原理
linux相關文章:linux教程
比較器相關文章:比較器工作原理
c++相關文章:c++教程
加速度計相關文章:加速度計原理
評論