Android記憶體分析和調優(下)
最後一部分是關於native heap,.dex,/dev/other的優化。
Native Heap分析和優化
android的DDMS可以幫助檢視c++ native heap的使用,但需要一定的配置,而且必須是root的手機。
- 在~/.android/ddms.cfg增加"native=true"。這樣子ddms才會有native heap的tab。
- 指向下面adb命令開啟malloc的debug模式
adb root
adb shell setprop libc.debug.malloc 1
adb shell stop
adb shell start - 開啟standalone的DDMS(不是eclipse中那個,是獨立的應用程式,sdk目錄下有),然後在native heap這個tab下,可以檢視native heap的分配情況。
在很多手機上,即使執行了這些命令,還是看不到結果。原因是很多手機上並沒有安裝debug版本的malloc庫(包括libc_malloc_debug_leak.so 和 libc_malloc_debug_qemu.so)。這篇經常被引用的文章介紹了一種方法。是從供大家刷機用的CyanogenMod image中提取這兩個檔案,然後拷貝到自己的機器上。可以參考那片文章的具體步驟。
下面的問題是隻能看到地址而不知道檔名和行號。至少有下面一些辦法
- 使用ndk中的arm-linux-androideabi-gdb(android ndk的gdb)來開啟.so檔案。這裡的.so不能使apk中使用的,因為那個已經把symbol給strip了。而應該使用 ***\obj\local\armeabi\***.so,這個是帶著symbol的。
然後可以在gdb中使用info symbol 0x000xxxxx來定位到地址對應的函式名。這裡的0x000xxxxx是ddms中地址把前三位變成0。因為gdb .so中使用.so的靜態地址,而ddms中的地址經過動態連結,是記憶體的虛擬地址。但動態連結並不改變地址的後五位,所以這裡後五位保持不變,前三位變成0,從而轉換為so的靜態地址。
然後用info line xxx.cpp:xxx來定位具體行。
這個方法比較繁瑣,因為當時自己沒找到好辦法,就這麼用的。 - 用ndk的arm-linux-androideabi-addr2line。後面跟so和0x000xxxxx。跟gdb差不多,會簡單一些。
- 有人說設定PATH加上包含addr2line的目錄,然後再設定ANDROID_PRODUCT_OUT可以在ddms中直接顯示函式名和行號,但沒有試過。
/other/dev分析和優化
自己用的是4.2版本的android。每次開啟preference setting,/other/dev的private dirty都會增加很多(10M作用),並且不會釋放。通過檢視smaps,發現是/dev/pvrsrvkm導致的(4.3後裝置名改為kgsl-3d0)。這個是顯示相關的裝置,按我的理解,大概是視訊記憶體(如果沒有獨立視訊記憶體,那是用於顯示的記憶體)。通過網上查詢,並不是只有我遇到這個問題。例如chrome也有這個問題。但還是不知道為何這個會增加。在一通亂試後,發現如果對activity設定android:hardwareAccelerated=false,就能解決。此時只增加shared dirty,並且關掉activity,記憶體會被釋放。後來再查,看到stackoverflow上這篇文章,才知道這是4.2的一個bug。4.3和4.1都沒有問題。
.Dex mmaps優化
這個是java程式碼編譯只會的.dex檔案的大小。
開始自己使用eclipse編譯出來的apk作效能分析,發現這個也有幾M。但release版本的卻不到1M。轉念一想,原來是proguard的作用。proguard是android自帶的混淆器,會對java的類名,函式名,變數名等重新命名,給一個非常短的名字。有兩個作用,一個是使得反編譯的程式碼不容易理解,另一個就是減少了dex檔案的大小。經過這次記憶體分析,才發現其效果還是非常明顯的。
因為proguard無法對res下的layout,xml檔案做混淆,所以他們引用到的java類(例如一些view類)的名字是不能被改變的。所以一個小經驗是讓xml檔案儘量少的引用java類,從而提高混淆的比例。
總結
關於android記憶體優化,自己就先做了這些。整體思路就是從巨集觀到微觀,利用各種工具和網路資料,從記憶體佔用量最多的模組下手,一步步的分析原因,解決問題。再細化下去,還有很多程式碼級別的優化,例如perf tips裡介紹了很多經驗,memory efficient java也很值得參考。有時間再在這個級別做更多的優化。
相關文章
- JVM效能調優,記憶體分析工具JVM記憶體
- 效能調優(cpu/IO/JVM記憶體分析)JVM記憶體
- Android記憶體優化Android記憶體優化
- MongoDB記憶體使用分析和優化MongoDB記憶體優化
- 記憶體調優實戰記憶體
- 分析並優化 Android 應用記憶體佔用優化Android記憶體
- Android Note - 記憶體優化Android記憶體優化
- Android效能優化篇之記憶體優化--記憶體洩漏Android優化記憶體
- 關於redis記憶體分析,記憶體優化Redis記憶體優化
- 淺談Android記憶體優化Android記憶體優化
- Android記憶體優化全解析Android記憶體優化
- Android 效能優化之記憶體優化Android優化記憶體
- Android 是如何管理 App 記憶體的 — Android 記憶體優化第二彈AndroidAPP記憶體優化
- Sieve—Android 記憶體分析系統Android記憶體
- SAP專家培訓之NetweaverABAP記憶體管理和記憶體調優最佳實踐記憶體
- Android記憶體優化之圖片優化Android記憶體優化
- SAP專家培訓之Netweaver ABAP記憶體管理和記憶體調優最佳實踐記憶體
- Android記憶體洩漏監控和優化技巧總結Android記憶體優化
- 實踐App記憶體優化:如何有序地做記憶體分析與優化APP記憶體優化
- 2.記憶體優化(二)優化分析記憶體優化
- android效能評測與優化-記憶體Android優化記憶體
- android記憶體管理機制與優化Android記憶體優化
- (2)Linux效能調優之Linux記憶體體系Linux記憶體
- 【JVM】堆體系結構及其記憶體調優JVM記憶體
- Linux記憶體洩露案例分析和記憶體管理分享Linux記憶體洩露
- Presto記憶體調優及原理(基礎篇)REST記憶體
- Android記憶體優化(四)解析Memory Monitor、Allocation Tracker和Heap DumpAndroid記憶體優化
- Android 分割槽和記憶體監控Android記憶體
- Android記憶體管理Android記憶體
- Android系統Bitmap記憶體分配原理與優化Android記憶體優化
- weblogic 記憶體調整Web記憶體
- Linux效能優化:記憶體使用情況分析Linux優化記憶體
- Windbg下使用dump分析記憶體溢位記憶體溢位
- Android深度效能優化--記憶體優化(一篇就夠)Android優化記憶體
- Android 記憶體快取框架 LruCache 的原始碼分析Android記憶體快取框架原始碼
- ArkTS 中的記憶體調優與配置:最佳實踐記憶體
- Android記憶體洩漏Android記憶體
- Android 記憶體抖動Android記憶體
- Android 記憶體洩漏Android記憶體