整理下Android內存優化常用的幾種工具,top命令、adb shell dumpsys meminfo、Memory Profiler、LeakCanary、MAT
1. top
top命令是Linux下常用的性能分析工具,能夠實時顯示系統中各個進程的資源佔用狀況。
查看top命令的用法
$ adb shell top --help
usage: top [-Hbq] [-k FIELD,] [-o FIELD,] [-s SORT] [-n NUMBER] [-m LINES] [-d SECONDS] [-p PID,] [-u USER,]
Show process activity in real time.
-H Show threads
-k Fallback sort FIELDS (default -S,-%CPU,-ETIME,-PID)
-o Show FIELDS (def PID,USER,PR,NI,VIRT,RES,SHR,S,%CPU,%MEM,TIME+,CMDLINE)
-O Add FIELDS (replacing PR,NI,VIRT,RES,SHR,S from default)
-s Sort by field number (1-X, default 9)
-b Batch mode (no tty)
-d Delay SECONDS between each cycle (default 3)
-m Maximum number of tasks to show
-n Exit after NUMBER iterations
-p Show these PIDs
-u Show these USERs
-q Quiet (no header lines)
Cursor LEFT/RIGHT to change sort, UP/DOWN move list, space to force
update, R to reverse sort, Q to exit.
複製代碼
使用top命令顯示一次進程信息,以便講解進程信息中各字段的含義
^[[41;173RTasks: 754 total, 1 running, 753 sleeping, 0 stopped, 0 zombie
Mem: 5.5G total, 5.4G used, 165M free, 76M buffers
Swap: 2.5G total, 789M used, 1.7G free, 2.4G cached
800%cpu 100%user 3%nice 54%sys 641%idle 0%iow 3%irq 0%sirq 0%host
PID USER PR NI VIRT RES SHR S[%CPU] %MEM TIME+ ARGS
15962 u0_a894 10 -10 6.6G 187M 76M S 75.6 3.2 8:16.55 asia.bluepay.cl+
785 system -2 -8 325M 13M 7.6M S 29.7 0.2 84:03.91 surfaceflinger
25255 shell 20 0 35M 2.7M 1.6M R 21.6 0.0 0:00.16 top -n 1
739 system -3 -8 177M 3.6M 2.2M S 10.8 0.0 16:00.36 android.hardwar+
16154 u0_i9086 10 -10 1.3G 40M 19M S 5.4 0.6 0:46.18 com.google.andr+
13912 u0_a87 20 0 17G 197M 86M S 5.4 3.4 23:56.88 com.tencent.mm
24789 root RT -2 0 0 0 D 2.7 0.0 0:01.36 [mdss_fb0]
24704 root 20 0 0 0 0 S 2.7 0.0 0:01.20 [kworker/u16:12]
20096 u0_a94 30 10 6.1G 137M 53M S 2.7 2.3 0:31.45 com.xiaomi.mark+
2272 system 18 -2 8.7G 407M 267M S 2.7 7.1 191:11.32 system_server
744 system RT 0 1.3G 1.6M 1.4M S 2.7 0.0 72:22.41 android.hardwar+
442 root RT 0 0 0 0 S 2.7 0.0 5:59.68 [cfinteractive]
291 root -3 0 0 0 0 S 2.7 0.0 5:00.17 [kgsl_worker_th+
10 root 20 0 0 0 0 S 2.7 0.0 1:55.84 [rcuop/0]
7 root 20 0 0 0 0 S 2.7 0.0 2:46.82 [rcu_preempt]
25186 shell 20 0 34M 1.9M 1.4M S 0.0 0.0 0:00.71 logcat -v long +
25181 root 20 0 0 0 0 S 0.0 0.0 0:00.00 [kworker/2:3]
25137 root 20 0 0 0 0 S 0.0 0.0 0:00.00 [kworker/1:3]
25118 system 20 0 5.2G 83M 54M S 0.0 1.4 0:01.05 com.android.set+
24946 u0_a57 20 0 5.1G 60M 37M S 0.0 1.0 0:00.82 com.xiaomi.acco+
複製代碼
第 1 行:進程信息
- 總共(total):754個
- 運行中(running)狀態:1個
- 休眠(sleeping)狀態:753個
- 停止(stopped)狀態:0個
- 殭屍(zombie)狀態:0個
第 2 行:內存信息
- 5.5G total:物理內存總量
- 5.4G used:使用中的內存量
- 165M free:空閑內存量
- 76M buffers: 緩存的內存量
第 3 行:Swap分區信息
- 2.5G total:交換區總量
- 789M used:使用的交換區大小
- 1.7G free:空閑交換區大小
- 2.4G cached:緩衝的交換區大小
內存監控時,可以監控swap交換分區的used,如果這個數值在不斷的變化,說明內核在不斷進行內存和swap的數據交換,這是內存不夠用了。
第 4 行:CPU信息
- 800%cpu:8核cpu
- 100%user:用戶進程使用CPU佔比
- 3%nice:優先值為負的進程佔比
- 54%sys:內核進程使用CPU佔比
- 641%idle:除IO等待時間以外的其它等待時間佔比
- 0%iow:IO等待時間佔比
- 3%irq:硬中斷時間佔比
- 0%sirq:軟中斷時間佔比
第 5 行及以下:各進程的狀態監控
- PID:進程id
- USER:進程所屬用戶
- PR:進程優先級
- NI:nice值,負值表示高優先級,正值表示低優先級
- VIRT:進程使用的虛擬內存總量,VIRT=SWAP+RES
- RES:進程使用的、未被換出的物理內存大小,RES=CODE+DATA
- SHR:共享內存大小
- S:進程狀態
- %CPU:上次更新到現在的CPU佔用時間比
- %MEM:使用物理內存佔比
- TIME+:進程時間的CPU時間總計,單位1/100秒
- ARGS:進程名
2. dumpsys meminfo
首先了解下Android中最重要的四大內存指標的概念
指標 | 全稱 | 含義 | 等價 |
USS | Unique Set Size | 獨佔物理內存 | 進程獨佔的內存 |
PSS | Proportional Set Size | 實際使用物理內存 | PSS = USS + 按比例包含共享庫內存 |
RSS | Resident Set Size | 實際使用物理內存 | RSS = USS + 包含共享庫內存 |
VSS | Virtual Set Size | 虛擬耗用內存 | VSS = 進程佔用內存(包括虛擬耗用) + 共享庫(包括比例分配部分) |
我們主要使用USS和PSS來衡量進程的內存使用情況
dumpsys meminfo命令展示的是系統整體內存情況,內存項按進程進行分類
$ adb shell dumpsys meminfo
Applications Memory Usage (in Kilobytes):
Uptime: 168829244 Realtime: 1465769995
// 根據進程PSS佔用值從大到小排序
Total PSS by process:
272,029K: system (pid 2272)
234,043K: com.tencent.mm (pid 13912 / activities)
185,914K: com.android.systemui (pid 13606)
107,294K: com.tencent.mm:appbrand0 (pid 5563)
101,526K: com.tencent.mm:toolsmp (pid 9287)
96,645K: com.miui.home (pid 15116 / activities)
...
// 以oom來劃分,會詳細列舉所有的類別的進程
Total PSS by OOM adjustment:
411,619K: Native
62,553K: android.hardware.camera.provider@2.4-service (pid 730)
21,630K: logd (pid 579)
16,179K: surfaceflinger (pid 785)
...
272,029K: System
272,029K: system (pid 2272)
361,942K: Persistent
185,914K: com.android.systemui (pid 13606)
37,917K: com.android.phone (pid 2836)
23,510K: com.miui.contentcatcher (pid 3717)
...
36,142K: Persistent Service
36,142K: com.android.bluetooth (pid 26472)
101,198K: Foreground
72,743K: com.miui.securitycenter.remote (pid 4125)
28,455K: com.android.settings (pid 30919 / activities)
338,088K: Visible
96,645K: com.miui.home (pid 15116 / activities)
46,939K: com.miui.personalassistant (pid 31043)
36,491K: com.xiaomi.xmsf (pid 4197)
...
47,703K: Perceptible
17,826K: com.xiaomi.metoknlp (pid 4477)
10,748K: com.lbe.security.miui (pid 5097)
10,528K: com.xiaomi.location.fused (pid 4563)
8,601K: com.miui.mishare.connectivity (pid 4227)
13,088K: Perceptible Low
13,088K: com.miui.analytics (pid 19306)
234,043K: Backup
234,043K: com.tencent.mm (pid 13912 / activities)
22,028K: A Services
22,028K: com.miui.powerkeeper (pid 29762)
198,787K: Previous
33,375K: com.android.quicksearchbox (pid 31023)
23,278K: com.google.android.webview:sandboxed_process0:org.chromium.content.app.SandboxedProcessService0:0 (pid 16154)
171,434K: B Services
45,962K: com.tencent.mm:push (pid 14095)
31,514K: com.tencent.mobileqq:MSF (pid 12051)
22,691K: com.xiaomi.mi_connect_service (pid 22821)
...
538,062K: Cached
107,294K: com.tencent.mm:appbrand0 (pid 5563)
101,526K: com.tencent.mm:toolsmp (pid 9287)
72,112K: com.tencent.mm:tools (pid 9187)
...
// 按內存的類別來進行劃分
Total PSS by category:
692,040K: Native
328,722K: Dalvik
199,826K: .art mmap
129,981K: .oat mmap
126,624K: .dex mmap
124,509K: Unknown
92,666K: .so mmap
68,189K: Dalvik Other
53,491K: .apk mmap
44,104K: Gfx dev
28,099K: Other mmap
24,960K: .jar mmap
7,956K: Ashmem
3,700K: Stack
3,368K: Other dev
450K: .ttf mmap
4K: Cursor
0K: EGL mtrack
0K: GL mtrack
0K: Other mtrack
// 手機整體內存使用情況
Total RAM: 5,862,068K (status normal)
Free RAM: 3,794,646K ( 538,062K cached pss + 3,189,244K cached kernel + 0K cached ion + 67,340K free)
Used RAM: 2,657,473K (2,208,101K used pss + 449,372K kernel)
Lost RAM: 487,987K
ZRAM: 219,996K physical used for 826,852K in swap (2,621,436K total swap)
Tuning: 256 (large 512), oom 322,560K, restore limit 107,520K (high-end-gfx)
複製代碼
查看單個進程的內存信息,命令如下
adb shell dumpsys meminfo [pid | packageName]
複製代碼
我們查看下微信的內存信息
$ adb shell dumpsys meminfo com.tencent.mm
Applications Memory Usage (in Kilobytes):
Uptime: 169473031 Realtime: 1466413783
** MEMINFO in pid 13912 [com.tencent.mm] **
Pss Private Private SwapPss Heap Heap Heap
Total Dirty Clean Dirty Size Alloc Free
------ ------ ------ ------ ------ ------ ------
Native Heap 51987 51924 0 61931 159044 139335 19708
Dalvik Heap 74302 74272 8 2633 209170 184594 24576
Dalvik Other 10136 10136 0 290
Stack 84 84 0 8
Ashmem 2 0 0 0
Gfx dev 8808 8808 0 0
Other dev 156 0 156 0
.so mmap 9984 984 7436 8493
.jar mmap 1428 0 560 0
.apk mmap 2942 0 1008 0
.ttf mmap 1221 0 1064 0
.dex mmap 31302 44 30004 528
.oat mmap 2688 0 232 0
.art mmap 2792 2352 40 3334
Other mmap 6932 2752 632 0
Unknown 4247 4232 4 7493
TOTAL 293721 155588 41144 84710 368214 323929 44284
App Summary
Pss(KB)
------
Java Heap: 76664
Native Heap: 51924
Code: 41332
Stack: 84
Graphics: 8808
Private Other: 17920
System: 96989
TOTAL: 293721 TOTAL SWAP PSS: 84710
Objects
Views: 623 ViewRootImpl: 1
AppContexts: 9 Activities: 1
Assets: 12 AssetManagers: 0
Local Binders: 198 Proxy Binders: 183
Parcel memory: 46 Parcel count: 185
Death Recipients: 125 OpenSSL Sockets: 1
WebViews: 0
SQL
MEMORY_USED: 156
PAGECACHE_OVERFLOW: 13 MALLOC_SIZE: 117
DATABASES
pgsz dbsz Lookaside(b) cache Dbname
4 28 46 721/26/4 /data/user/0/com.tencent.mm/databases/Scheduler.db
Asset Allocations
: 409K
: 12K
: 1031K
複製代碼
- App Summary各項指標解讀如下,通常我們需要重點關注Java Heap和Native Heap的大小,如果持續上升,有可能存在內存泄露。
屬性 | 內存組成 |
Java Heap | Dalvik Heap的Private Dirty + .art mmap的Private Dirty&Private Clean |
Native Heap | Native Heap的Private Dirty |
Code | .so mmap + .jar mmap + .apk mmap + .ttf.mmap + .dex.mmap + .oat mmap的Private Dirty&Private Clean |
Stack | Stack的Private Dirty |
Graphics | Gfx dev + EGL mtrack + GL mtrack的Private Dirty&Private Clean |
- Objects中Views、Activities、AppContexts的異常可以判斷有內存泄露,比如剛退出應用,查看Activites是否為0,如果不為0,則有Activity沒有銷毀。
3. Memory Profiler
Memory Profiler是 Android Profiler 中的一個組件,實時圖表展示應用內存使用量,識別內存泄露和抖動,提供捕獲堆轉儲,強制GC以及跟蹤內存分配的能力。
Android Profiler官方文檔
4. Leak Canary
非常好用的內存泄露檢測工具,對於Activity/Fragment的內存泄露檢測非常方便。
Square公司開源 官網地址,原理後面單獨分析。
5. MAT
MAT是Memory Analyzer tool的縮寫,是一個非常全面的分析工具,使用相對複雜點。 關於安裝和配置有很多很好的文章結束,這裡就不單獨講了,後面分析具體案例。
Android 內存優化篇 – 使用profile 和 MAT 工具進行內存泄漏檢測
使用Android Studio和MAT進行內存泄漏分析
內存問題高效分析方法
- 接入LeakCanary,監控所有Activity和Fragment的釋放,App所有功能跑一遍,觀察是否有抓到內存泄露的地方,分析引用鏈找到並解決問題,如此反覆,直到LeakCanary檢查不到內存泄露。
- adb shell dumpsys meminfo命令查看退出界面後Objects的Views和Activities數目,特別是退出App後數目為否為0。
- 打開Android Studio Memory Profiler,反覆打開關閉頁面多次,點擊GC,如果內存沒有恢復到之前的數值,則可能發生了內存泄露。再點擊Profiler的垃圾桶圖標旁的heap dump按鈕查看當面內存堆棧情況,按包名找到當前測試的Activity,如果存在多份實例,則很可能發生了內存泄露。
- 對於可疑的頁面dump出內存快照文件,轉換後用MAT打開,針對性的分析。
- 觀察Memory Profiler每個頁面打開時的內存波峰和抖動情況,針對性分析。
- 開發者選項中打開「不保留後台活動」,App運行一段時間後退到後台,觸發GC,dump內存快照。MAT分析靜態內容是否有可以優化的地方,比如圖片緩存、單例、內存緩存等。
原創文章,作者:投稿專員,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/219104.html