讀書筆記2-記憶體優化篇

niknowzcd發表於2019-02-15

本系列博文 基於是前微信高階工程師張紹文專欄 《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記憶體測量

如何著手記憶體優化

  1. 裝置分級或者說記憶體分級

    簡單來說就是高記憶體,新手機效果全開.老爺機便宜貨保留基本功能。

    device-year-class是facebook開源的一個庫.該庫會根據手機的記憶體,CPU核心數和頻率

    得出手機屬於那個年份。

    而我們也可以根據這個年份來判斷,效果全開還是保留基本功能。

    補充部分:

    • 一個空程式也會佔用10MB的記憶體,所以對於一些低端機就不要開太多程式了

    • 安裝包中的程式碼、資源、圖片以及 so 庫的體積,跟他們佔用的記憶體有很大關係。

      所以apk優化還是有必要的。

  2. Bitmap優化

    統一圖片庫,主要是為了統一圖片的呼叫入口.記憶體不足的時候可以降低圖片格式,選用更合理的縮放演算法。

    另外一點,張老師在課中提到需要做圖片監控,一般為了針對大圖片和重複圖片。(關於這方面,我也接觸的不多,就不誤導大家了。)

  3. 記憶體洩漏

    記憶體洩漏主要分兩種情況,一種是同一個物件洩漏,還有一種是每次都會洩露新的物件。

    最後,給自己公眾號打個廣告,【碼農的嘮叨】聊技術,聊熱文,聊網際網路趣事,也發嘮叨

    qrcode_for_gh_5febf245550e_258

相關文章