本系列博文 基於是前微信高階工程師張紹文專欄 《Android開發高手課》的讀書筆記。
文章所寫內容是本人讀完的感悟,需要原文的朋友請自行購買。
記憶體優化篇
寫在開頭.
越讀張老師的課,越會發現有很多知識完全沒有接觸過,課程的留言下方也有很多人反應說課程有點深。
秉持著"大家好才是真的好"的理念,之後的筆記都會記錄一些大家容易理解的內容,
至於有些設計比較深的內容,一筆帶過。有興趣的朋友可以自行了解。
手機執行記憶體(RAM)作為 App 執行過程中臨時性資料暫時儲存的記憶體介質,因為體積和功耗的原因,沒有直接採用PC上DDR的架構,而是該用LPDDR,可以理解為Lower PowerDDR.
記憶體不足所帶來的問題
1.**異常:**其中異常包括OOM、記憶體分配失敗這些崩潰,也包括因為整體記憶體不足導致應用被殺死、裝置重啟等問題。
2.**卡頓:**Java 記憶體不足會導致頻繁 GC,而GC便會引起卡頓,這個問題在Dalvik 虛擬機器比較明顯,而ART虛擬機器在記憶體管理跟回收策略上都做大量優化,所以卡頓現象沒那麼嚴重。
如果想要測試GC的效能,可以通過adb命令獲取ANR日誌.
//adb 命令
adb shell kill -S QUIT PID
adb pull /data/anr/traces.txt
//ANR日誌
sticky concurrent mark sweep paused: Sum: 5.491ms 99% C.I. 1.464ms-2.133ms Avg: 1.830ms Max: 2.133ms // GC 暫停時間
Total time spent in GC: 502.251ms // GC 總耗時
Mean GC size throughput: 92MB/s // GC 吞吐量
Mean GC object throughput: 1.54702e+06 objects/s
複製程式碼
除了頻繁GC會造成卡頓之外,實體記憶體不足時系統會觸發low memory killer 機制,進而影響手機效能。
關於實體記憶體不足引起的卡頓現象,不只發生在android系統上,最近筆者的蘋果手機也因為實體記憶體不足,卡頓現象明顯。
記憶體優化的兩大誤區
1.記憶體佔用越少越好
有些朋友在記憶體優化的時候,總是覺得記憶體佔有越低越好,實則不然。
假設手機的記憶體無限大,所有介面圖片都不需要回收,這時你切換介面就能達到秒載入的體驗.這種體驗自然是最好的。
當然記憶體無限大是不存在的,但也反應了一點,記憶體使用高的時候效能會更好。
我們應該秉承著“用時分配,及時釋放”的理念來優化記憶體。
2.Native記憶體不用管
在說Native記憶體之前,先來談一談常見的OOM。
Android系統會給每一個程式分配一個最大java堆.如果該程式申請的空間超過這個閾值時,就會丟擲OOM異常。
所以程式發生OMM並不表示RAM(實體記憶體)不足
這樣設計的目的是為了讓Android系統能同時讓比較多的程式常駐記憶體(RAM)。
Native記憶體起到什麼作用?
拿常見的例子來說明,大家都知道android的記憶體大戶是bitmap,OOM出現也多是因為圖片。
-
在Android3.0之前,Bitmap物件放在java堆中,具體的畫素資料放在Native中,這樣做OOM的機率小了,但在圖片回收的時候,不一定能及時釋放Native記憶體中的圖片畫素資料。
-
於是在Android3.0~Android7.0期間,將Bitmap 物件和畫素資料統一放到 Java 堆中.這樣做資源是能及時回收了,但是OOM的問題又出現了。
-
Android8.0系統又覺得將Bitmap畫素資料放回到Native中,只是這時多了一個NativeAllocationRegistry來幫助Native記憶體的回收。
那麼8.0系統之後的手機效能優化對圖片部分是不是就沒有那麼必要了呢?畢竟圖片畫素資料放入到Native之後就不太會引起OOM。
當然也不是,雖說OOM的機率小了,但沒有回收的圖片依舊佔用著RAM,當RAM不夠的時候,手機會開啟
low memory killer 殺戮模式,後臺,桌面,服務,前臺,直至手機重啟。
所以該回收的記憶體還是得回收的,如果因為手機記憶體不足導致手機卡頓,刪點圖片,騰出點空間還是有效果的。
java記憶體和Native記憶體的測量方法
java記憶體測量
- Allocation Tracker
- MAT
Native記憶體測量
- Chromium 的AddressSanitize
- 除錯本地記憶體使用
如何著手記憶體優化
-
裝置分級或者說記憶體分級
簡單來說就是高記憶體,新手機效果全開.老爺機便宜貨保留基本功能。
device-year-class是facebook開源的一個庫.該庫會根據手機的記憶體,CPU核心數和頻率
得出手機屬於那個年份。
而我們也可以根據這個年份來判斷,效果全開還是保留基本功能。
補充部分:
-
一個空程式也會佔用10MB的記憶體,所以對於一些低端機就不要開太多程式了
-
安裝包中的程式碼、資源、圖片以及 so 庫的體積,跟他們佔用的記憶體有很大關係。
所以apk優化還是有必要的。
-
-
Bitmap優化
統一圖片庫,主要是為了統一圖片的呼叫入口.記憶體不足的時候可以降低圖片格式,選用更合理的縮放演算法。
另外一點,張老師在課中提到需要做圖片監控,一般為了針對大圖片和重複圖片。(關於這方面,我也接觸的不多,就不誤導大家了。)
-
記憶體洩漏
記憶體洩漏主要分兩種情況,一種是同一個物件洩漏,還有一種是每次都會洩露新的物件。
- Java 記憶體洩漏, 可以參考LeakCanary
- OOM監控 可以看看美團的Probe
- Native記憶體監控 微信 Android 終端記憶體優化實踐
最後,給自己公眾號打個廣告,【碼農的嘮叨】聊技術,聊熱文,聊網際網路趣事,也發嘮叨