關於 Android 系統流暢性的一些思考

關於 Android 系統流暢性的一些思考

來自專欄 Android Tips90 人贊了文章

本文首發:

http://www.androidperformance.com/2018/08/13/Some-Thoughts-on-the-Fluency-of-Android/?

www.androidperformance.com

最近一直想寫一些關於 Android 系統流暢度的東西,因為流暢度這個東西,是消費者最直接能體驗到的,再加上 Android 一直為人詬病的越用越卡頓,使得大家在提到安卓機的時候,都會有一絲陰影。這也是大部分人買手機首先會考慮 iPhone 的一個原因。

由於 Google 對 Android 持開放態度,各個手機廠商生產不同產品定位的機器,以及各個 Android 應用的質量良莠不齊,導致影響 Android 流暢度的因素非常非常多,並非大家簡單的以為是系統沒有優化好,很多時候你會發現,不同 SOC 但是相同的系統,體驗完全就是兩種。

所以我想和大家聊聊影響 Android 系統流暢性的一些原因,後續大家遇到卡頓的問題,也不會單純把鍋甩給系統,或許你卸載一個 App 就解決了呢.

我想從下面幾個方面展開聊這個話題

  1. 硬體層面
  2. 系統層面
  3. 應用層面
  4. 流暢度優化閉環

準備好了,那就開始吧,歡迎你加入討論

1. 硬體層面

CPU

cpu 是手機硬體裡面最核心的一個器件,這也是把 cpu 作為第一個來說的主要原因,cpu 之所以重要,是因為 Android 系統的運行過程中,大部分是跟 cpu 打交道,cpu 的能力強弱,直接決定了這款手機的檔次。

手機 cpu 目前主要有高通、華為、三星、聯發科四家在做,每家都有高中低檔,高端 cpu 的排名大概是 高通>華為>三星>聯發科,再具體點就是高通845>華為970>三星9810>聯發科X30. 具體的排名可以去這裡看:mydrivers.com/zhuanti/t

GPU

各個廠商提供的 SOC 裡面,通常包含了 cpu 和 gpu ,所以大部分情況下,只要一說 cpu,其 gpu 也是對應確定的,比如高通驍龍845 SOC 帶的 gpu 就是 Adreno 630。

gpu 的能力強弱更多的影響的是 gpu 強相關的應用和遊戲,比如絕地求生-刺激戰場 、 崩壞3 、極品飛車、狂野飆車等。反而王者榮耀這樣的遊戲更多的是吃 cpu 而不是 gpu。

Ram

隨著 Android 版本的更新,以及硬體的更新換代,Android 系統對內存的需求越來越強,目前4G內存的手機基本上已經成了標配,旗艦機器沒個 6G 或者 8G 你都不好意思說自己是旗艦。

內存主要影響系統行為,內存越大,系統就越可以以空間換時間:後台可以緩存更多的進程,殺進程不再那麼激進;可以根據用戶習慣預載入一些文件或者進程;各種虛擬機、hwui、進程的參數可以往寬鬆里調。反饋到用戶那裡,就是快。

當然如果後台進程多了又沒有管住在後台跑,那麼又會很耗電,有點得不償失,這也是為什麼國內的系統都會對進程管理這一塊進行魔改。

UFS && EMMC

ufs 和 emmc 都是面向移動端的 flash 標準,我們最長聽說的就是 emmc5.1 和 ufs 2.1 ,具體可以參考這篇文章:zhuanlan.zhihu.com/p/26

對於用戶來說,ufs 和 emmc 的差異主要在文件讀取速度、視頻載入速度、文件拷貝等方面,總之能上ufs就別考慮 emmc。

不過有時候這個也是需要 SOC 支持的,比如高通 660,就不支持 ufs,能不買就別買吧。

屏幕解析度

我們最常見的屏幕解析度是 1080P,即 1920*1080. 對用戶來說,屏幕解析度除了會影響視覺感官外,還會在系統某些地方有差異,比如截圖、錄屏、合成等操作。越高的屏幕解析度,在這裡的耗時就越久,也越耗電。

這也是部分 2K 手機在某些場景下,把解析度降低到 1080P 去運行的原因。比較失敗的一個例子就是當年的魅族 MX4 Pro ,在硬體性能不足以支撐 2K 的情況下,強行上了 2K 屏幕,導致很多情況下,用戶反饋又卡又耗電。

電池大小

電池大小決定著續航,也決定著手機設計,手機廠家往往需要在這兩者之間找一個平衡,在電池技術沒有突破的情況下,就算各家都有快充,還是建議用戶在選購手機的時候,盡量選大容量電池的手機,比如 Oppo Find X 或者 Vivo NEX,或者華為 Mate 10.

SoC 平台

SoC的全稱叫做:System-on-a-Chip,除了我們之前說的 cpu、gpu,Soc 上還有很多器件,具體可以看這篇文章:zhuanlan.zhihu.com/p/37 ,這裡就不展開講了。

SoC 是整個手機最重要的部分,是一切體驗的基礎。現在高通、三星、MTK 給手機廠家提供的硬體就是 Soc ,以及其配套的 Android 適配系統。手機廠商拿到這個之後,在其基礎上做整機的設計,系統這邊會在配套的 Android 適配系統上做移植,也就是把各家系統差異化的東西移植到新系統上。

從目前的高通、三星、MTK 三家的適配系統的質量來看,高通提供的適配系統是功能最完善的,高通在 AOSP 的基礎上,加上了高通自己的非常多的優化代碼,並提供了完善的參數供手機廠商去配置,總的來說開發起來是很舒服的,本身系統的問題不會太多,加上高通的文檔完善,支持速度快,國內那麼多手機廠商都在用高通也就不足為奇了。

至於專利費,該給的要給啊。

我們經常會說,如果魅族早點用高通的 Soc,早 TM 上市了。

2. 系統層面

應用的管控策略

大部分 Android 應用開發者對國內的手機廠商恨的咬牙切齒,最大的原因就是國內系統對應用管控這一塊進行了大量的魔改,除非你是 QQ 或者微信,否則滅了屏結果都一樣。

國內廠商這麼做,不是沒有原因的,國內應用廠商的全家桶相互喚醒,已經到了一種喪心病狂的地步,牽一髮而動全身,一點都不誇張。

我們遇到的很多用戶反饋的整機卡頓問題,抓 Trace 和 Log 來看,都是後台有應用在亂跑,或者後台大量的進程常駐,內存根本不夠,而這些普通用戶根本就不知道怎麼去處理。

所以國內廠商一般會在系統裡面做限制,以保障用戶的基礎體驗:

  1. 除非必須,一個應用偷偷拉起來另外一個應用的行為是不被允許的
  2. 除非必須,一個應用常駐後台是不被允許的
  3. 除非必須,一個應用在滅屏後在後台亂跑是不被允許的
  4. 除非必須,一個應用在後台長時間佔用 cpu 是不被允許的
  5. 除非必須,一個應用彈窗是不被允許的

另外手機廠商會有其他的邏輯清理後台的應用,儘管你是合理存在的。

對進程的嚴格管控,也導致了國內系統的體驗有一定的影響,首當其衝的是通知,如果一個應用沒有接入這個手機廠商提供的 push sdk,那麼他這輩子別想發通知給用戶了,如果接入了手機廠商提供的 sdk(目前大部分應用的普遍做法),由於應用不在後台,用戶點擊通知要等好久才可以進入到對應的界面,毫無用戶體驗可言。

內存策略

手機廠商常常會根據手機的內存大小來定製各種不同的策略,比如後台應用的緩存個數、LowMemoryKiller 的閾值、殺進程模塊的閾值、顯示模塊的緩存大小閾值、用戶最常用應用的個數等。

很多低端機用戶反饋卡頓,我們查看發現,內存是造成卡頓的主要元兇,在低內存的機器上,由於內存不足,系統會頻繁殺後台,同時也有頻繁的內存->文件,文件->內存 的操作,Trace 上很多 BlockIO,很多平時執行很快的操作,現在執行要很久,再加上部分進程被殺之後馬上重啟,重啟之後又被殺,cpu 佔用很高,此時就會很卡。

隨著 Android 系統和應用的更新,只會越來越吃內存,目前4G內存是標配,明年或許 6G 才是標配了,能上 8G 盡量上 8G。

進程調度策略

進程調度策略有時候也會影響用戶的流暢性,當應用的渲染鏈路上,有哪個環節因為某些原因,沒有被調度到的時候,很大可能會造成卡頓。

調度不到在 Trace 上的表現是 Runnable,常見的調度不到的情況有:

  1. 同時運行的進程太多,cpu 這邊的幾個核處理的任務基本都是滿的
  2. 進程優先順序較低
  3. 調度器過於不靈敏,不能及時響應大任務

另外由於 cpu 引起的卡頓情況還有:

  1. 從大核心掉落到小核心上,小核心處理能力不足,會造成短暫的卡頓
  2. 觸發溫控或者觸發低電量,此時某些系統會限制大核的使用,導致卡頓
  3. 系統鎖也是造成卡頓的一大元兇,尤其是 wms 鎖和 ams 鎖,再加上 binder 通信,relayoutWindow 了解一下?
  4. 核心頻率不足,導致函數執行時間過長導致卡頓
  5. 大核心被佔用,任務又調度不到小核,導致卡頓

系統調優往往需要針對上面的情況做對應的處理,給用戶一個好的用戶體驗。具體的調優方式,往往跟系統和 Soc 強相關,又涉及到 Kernel 和 功耗,改起來是牽一髮而動全身,需要非常謹慎。

渲染線程和主線程

Android 應用的渲染鏈路上最重要的就是主線程和渲染線程,主線程就是應用啟動時創建的 MainThread,對應的也會創建一個 RenderThread(硬體加速默認開啟),我們平時比較看重的 GPU Profile 那條線,基本就包含了主線程和渲染線程的各個階段的執行時間,從 GPU Profile ,就可以很容易看到應用的瓶頸

大部分應用的卡頓都發生在主線程和渲染線程上,比如:

  1. 較長時間的 input 事件處理
  2. 較長時間的動畫事件處理,比如 ListView 的新 Item 的生成
  3. 複雜界面的 Measure、 Layout、Draw
  4. 較大 Bitmap 的頻繁 upload
  5. 複雜渲染指令的執行

很多編程的不好的實現,都可以在上面幾個步驟裡面體現出來,這些都可以通過 Systrace 看出來。

當前應用的渲染鏈路上的一切優先順序都應該是最高的,後台的進程不應該對其造成影響,這也是系統優化的核心要素,不過要做到這一點也是比較難的,你很難考慮到所有的情況,比如有的用戶的使用環境就是很複雜,而且都是必須的,這時候就不是很好處理。

TripleBuffer

之前有提到 TripleBuffer,這個是 Project Butter 引進的,其中 Vsyncv 和 TripleBuffer 的引進使得 Android 的流暢度上了一個台階,關於這個可以參考這篇文章 : niorgai.github.io/2017/

對於用戶來說這個是透明的,影響的是 GPU Profile 的展示,有時候如果有一條線超過 16 ms 的警戒線,它不一定代表著卡頓,這就是 TrileBuffer 的作用。

後續我會有文章專門講這個,如何判斷是真正的卡頓。

虛擬機 - Art 和 Dalvik

對用戶來說,Art 虛擬機相比 Dalvik 虛擬機,最大的提升就是解放了應用的主線程,主線程不再頻繁被 GC 線程 Stop ,相應卡頓也減少了很多。

當然 Art 帶來的好處不止這一點,Art 隨著幾個大版本的縫縫補補,已經在很多地方遠遠超過了 Dalvik,有興趣的可以自己查一下。

溫控 && 低電量

之前提到,一旦觸發溫控或者低電量,系統會對資源做一定的限制,防止手機無限制過熱或者快速關機。這限制就包括

  1. 降低 cpu、gpu 最高頻率
  2. 減少可運行的 cpu 的核心數
  3. 殺掉部分後台進程
  4. 關閉部分特效
  5. 限制網路連接

總之,這些限制或多或少會對用戶造成影響,最大的影響就是卡頓,這就是很多人會遇到打遊戲的時候突然很卡的一個原因。

所以說選購手機的時候,除了要看 Soc,還要看散熱是否做的夠好,電池是否做的夠大。

3. 應用層面

複雜的布局

複雜的布局往往是應用卡頓的最主要的元兇之一,複雜的布局意味著更長的 Measure、Layout、Draw ,這會拖慢主線程的執行速度

ListView、RecyclerView 的新的 Item 在初始化的時候也會有類似的問題,由於此時一般是在滑動,這時候的卡頓感會更明顯,用戶也更容易察覺,這個從 Trace 上也很容易看出來。

過多的業務邏輯

過多業務邏輯導致的卡頓和響應慢的問題,拿淘寶來舉例子最合適不過了,每次你冷啟動淘寶的時候,進入主界面馬上滑動,總感覺跟吃了屎一樣,點按鈕點不動,滑界面滑不動,雖然最近的版本有優化,不過你找個低端 Android 機,還是原來的配方。

淘寶在啟動的時候,需要動態載入很多東西,導致主界面響應很慢,很多東西要動態載入完成後才可以操作,後台還有大量的 dex2oat 操作,可以說是很忙了。

內存顛簸

頻繁申請和釋放內存,會導致內存顛簸,從 AS 的內存監視器可以看到這一點,短時間內內存曲線上下跳動非常頻繁,這時候你需要檢查一下是否代碼寫的有問題。

慢網路

慢網路指的是用戶請求網路耗時很久,這會導致用戶在某些界面等待內容需要很久,比如知乎經常會出現這種情況,在用戶看來,這就是卡了。

不合理的設計

設計和性能往往不可兼得,需要從兩者之間做取捨,設計師的設計往往很炫酷,互相嵌套的動畫往往是程序員的噩夢,為了實現這些複雜的效果,程序員往往需要複雜的代碼來實現,這對應用的渲染鏈路的壓力是非常大的,而且在不同性能的機器上表現差異很大,高端機用戶覺得這個效果棒棒噠,低端機用戶卡的要罵娘。

程序員需要有這方面的知識和數據,好與設計師動之以情曉之以理。

不過用戶是很挑剔的,現在的用戶對性能的要求越來越高,哪怕是低端機用戶,所以合適的設計應該考慮到這部分用戶、或者針對低端機用戶做區分。

代碼實現錯誤

俗稱 bug ,很多程序員不喜歡解決性能問題,因為這個東西解決起來,性價比很低,拿我司的程序員來說,解一個性能問題的時間,可以解決十幾個界面顯示的問題,還未必能真的解決。

不過由於代碼實現錯誤引起的性能問題,必須要最高優先順序解決。

4. 流暢度優化閉環

實驗室監控 && 模擬用戶

開發階段就用各項數據來做監控和對比,盡量模擬用戶的使用環境,儘早暴漏性能問題,早日解決。

用戶流暢度數據收集

在用戶使用階段,收集性能數據,針對這些數據做分析,找出用戶最多遇到的性能問題,針對性地做優化。需要注意此時不能在用戶階段手機太多的信息,否則會導致觀察者效應

至於需要收集的數據,則需要根據相關度模型來做判斷,卡頓發生的時候,系統的哪些指標是可能導致卡頓的原因,那麼這些指標就是我們收集的數據。

另外用戶的場景判斷也非常重要,需要知道用戶是在哪個場景出現的卡頓,一旦用戶的數量到了一定的級別,這個是很容易發現問題的。

針對性地優化

大數據發現問題後,後續就是針對性地進行優化,把用戶最常遇到性能問題的場景進行排序,對最常見的場景進行調研和優化。很多時候需要與應用開發廠商進行溝通,

然後需要把這些場景納入到實驗室監控環境里,做到 實驗室監控 —> 模擬用戶 — > 大數據收集 —> 針對性優化 —> 實驗室監控補充. 這樣一個閉環。

推薦閱讀:

把那些流氓軟體都凍結起來,讓手機流暢又省電

TAG:科技 | 安卓優化 | Android |