Android | 内存指标与测量方法 目录 前置知识 1. 内存指标 2. 内存分析命令 3. 内存分析工具

点赞关注,不再迷路,你的支持对我意义重大!

🔥 Hi,我是丑丑。本文 「Android 路线」| 导读 —— 从零到无穷大 已收录,这里有 Android 进阶成长路线笔记 & 博客,欢迎跟着彭丑丑一起成长。(联系方式在 GitHub)


目录


前置知识

这篇文章的内容会涉及以下前置 / 相关知识,贴心的我都帮你准备好了,请享用~


1. 内存指标

在讨论具体的内存优化方法之前,我们先来讨论内存的指标与分析工具。首先你需要理解这些内存指标

1.1 最大堆内存

为了避免应用滥用内存,Android 系统会限制应用可以申请的最大堆内存,超过此限制就会抛出 OOM 异常。Android 设备出厂后,最大堆内存就已经确定,相关的配置位于系统根目录/system/build.prop文件中,我们可以通过命令查看:

命令:
adb shell cat /system/build.prop
------------------------------------------------------------------
输出:
...
dalvik.vm.heapstartsize=16m           [进程启动的初始堆内存]
dalvik.vm.heapgrowthlimit=128m        [进程最大堆内存]
dalvik.vm.heapsize=192m               [进程最大堆内存(开启 largeHeap="true")]
dalvik.vm.heaptargetutilization=0.75
dalvik.vm.heapminfree=512k
dalvik.vm.heapmaxfree=8m
...
虚拟机参数 描述
dalvik.vm.heapstartsize 进程启动的初始堆内存
dalvik.vm.heapgrowthlimit 进程最大堆内存
dalvik.vm.heapsize 进程最大堆内存(开启 largeHeap="true")
dalvik.vm.heaptargetutilization
dalvik.vm.heapminfree
dalvik.vm.heapmaxfree

在 App 虚拟机启动时,会读取/system/build.prop文件的配置,源码位于:AndroidRuntime.cpp

->虚拟机启动
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote) {
    ...
    parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
    parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
    parseRuntimeOption("dalvik.vm.heapgrowthlimit", heapgrowthlimitOptsBuf, "-XX:HeapGrowthLimit=");
    parseRuntimeOption("dalvik.vm.heapminfree", heapminfreeOptsBuf, "-XX:HeapMinFree=");
    parseRuntimeOption("dalvik.vm.heapmaxfree", heapmaxfreeOptsBuf, "-XX:HeapMaxFree=");
    parseRuntimeOption("dalvik.vm.heaptargetutilization", heaptargetutilizationOptsBuf, "-XX:HeapTargetUtilization=");
    ...
}

需要注意的是,配置dalvik.vm.heapgrowthlimit限制的仅仅是 Java 堆内存,本地内存时不受其限制的。换句话说,应用可以使用的最大内存其实是可以大于最大堆内存的。

1.2 进程到底占用了多少内存?

在 Linux 里,一个进程占用的内存有四种指标,分别是:

内存指标 全称 关系
VSS Virtual Set Size 一个进程可访问的地址空间
RSS Resident Set Size 一个进程实际占用的内存大小(包含共享库占用的内存)
PSS Proportional Set Size 一个进程实际占用的内存大小(按比例计算共享库占用的内存)
USS Unique Set Size 进程独立占用的物理内存(不包含共享库占用的内存)

一般来说内存占用大小有如下规律:VSS >= RSS >= PSS >= USS。

  • VSS: 一个进程可访问的地址空间,其大小还包括分配但未使用的内存,因此对于分析进程占用内存用处不大;

  • RSS: 一个进程实际占用的内存大小,RSS 同样也不太准确,主要是因为 RSS 还包括该进程使用的共享库。而一个共享库是可以被多个进程共享的,以至于所有进程的 RSS 相加会超过物理内存很多;

  • PSS: 一个进程实际占用的内存大小,相对于 RSS,它是按照比例计算共享库占用的内存的。例如一个共享库被 N 个进程共享,那么 PSS 只会计算 1/N 共享库内存。PSS 在有些时候也是有偏差的,例如进程 A 和进程 B 使用同一个共享库没并且 B 在 A 之后启动,那么在 B 启动的那一刻,A 的 PSS 会突然断崖式降低,即时 A 并没有做任何内存释放,这会给分析进程内存行为带来麻烦。

  • USS: 一个进程占用的私有内存大小,相对于其它指标,USS 不包含共享库占用的内存,只包含进程独占的内存部分。如果该进程终止,USS 就是实际被返还给系统的内存大小。

—— 图片引用自 https://www.cnblogs.com/sunsky303/p/13494977.html —— sunsky303 著


2. 内存分析命令

Applications Memory Usage (in Kilobytes):
Uptime: 11344873 Realtime: 11344873

Total PSS by process:
     85,517K: cn.kidyn.qdmedical160 (pid 4273 / activities)
     67,985K: system (pid 1639)
     60,472K: com.android.systemui (pid 1777 / activities)
     58,943K: org.chromium.webview_shell (pid 3990 / activities)
     29,429K: com.android.launcher3 (pid 2331 / activities)
     24,383K: cn.kidyn.qdmedical160:pushservice (pid 4466)
     21,077K: com.android.inputmethod.latin (pid 1744)
     20,671K: com.android.phone (pid 1878)
     20,603K: zygote (pid 1313)
     14,790K: cn.kidyn.qdmedical160:core (pid 4320)
     14,114K: cn.kidyn.qdmedical160:todaystep (pid 5236)
     11,734K: android.process.acore (pid 2422)
     10,912K: com.android.packageinstaller (pid 3718)
     10,824K: com.android.quicksearchbox (pid 2386 / activities)
      6,597K: logd (pid 1256)
      6,249K: com.android.calendar (pid 5161)
      6,179K: com.android.deskclock (pid 2093)
      6,084K: libweexjsb.so (pid 5286)
      6,080K: libweexjsb.so (pid 4516)
      6,076K: libweexjsb.so (pid 4406)
      6,068K: libweexjsb.so (pid 4399)
      5,361K: com.android.gallery3d (pid 2539)
      5,247K: com.android.providers.calendar (pid 5173)
      3,999K: com.android.printspooler (pid 2285)
      3,848K: com.android.defcontainer (pid 2752)
      3,817K: android.ext.services (pid 2176)
      3,811K: audioserver (pid 1314)
      3,739K: mediaserver (pid 1322)
      3,365K: com.svox.pico (pid 2781)
      3,117K: media.extractor (pid 1321)
      2,591K: media.codec (pid 1319)
      2,533K: cameraserver (pid 1315)
      1,930K: surfaceflinger (pid 1308)
      1,907K: mediadrmserver (pid 1320)
      1,583K: wpa_supplicant (pid 1894)
      1,549K: netd (pid 1323)
      1,446K: vold (pid 1265)
      1,319K: drmserver (pid 1316)
      1,253K: sdcard (pid 1789)
      1,241K: sdcard (pid 1860)
      1,085K: /init (pid 1)
      1,074K: hostapd (pid 1596)
      1,045K: adbd (pid 1342)
        927K: keystore (pid 1318)
        718K: rild (pid 1324)
        698K: fingerprintd (pid 1326)
        681K: installd (pid 1317)
        667K: gatekeeperd (pid 1327)
        635K: lmkd (pid 1306)
        572K: ueventd (pid 930)
        551K: logcat (pid 1312)
        520K: healthd (pid 1303)
        493K: dumpsys (pid 5583)
        483K: dnsmasq (pid 1599)
        482K: servicemanager (pid 1307)
        470K: sh (pid 1311)
        442K: sh (pid 1518)
        435K: perfprofd (pid 1333)
        324K: ipv6proxy (pid 1569)
        277K: debuggerd (pid 1264)
        239K: debuggerd:signaller (pid 1267)

Total PSS by OOM adjustment:
     92,345K: Native
         20,603K: zygote (pid 1313)
          6,597K: logd (pid 1256)
          6,084K: libweexjsb.so (pid 5286)
          6,080K: libweexjsb.so (pid 4516)
          6,076K: libweexjsb.so (pid 4406)
          6,068K: libweexjsb.so (pid 4399)
          3,811K: audioserver (pid 1314)
          3,739K: mediaserver (pid 1322)
          3,117K: media.extractor (pid 1321)
          2,591K: media.codec (pid 1319)
          2,533K: cameraserver (pid 1315)
          1,930K: surfaceflinger (pid 1308)
          1,907K: mediadrmserver (pid 1320)
          1,583K: wpa_supplicant (pid 1894)
          1,549K: netd (pid 1323)
          1,446K: vold (pid 1265)
          1,319K: drmserver (pid 1316)
          1,253K: sdcard (pid 1789)
          1,241K: sdcard (pid 1860)
          1,085K: /init (pid 1)
          1,074K: hostapd (pid 1596)
          1,045K: adbd (pid 1342)
            927K: keystore (pid 1318)
            718K: rild (pid 1324)
            698K: fingerprintd (pid 1326)
            681K: installd (pid 1317)
            667K: gatekeeperd (pid 1327)
            635K: lmkd (pid 1306)
            572K: ueventd (pid 930)
            551K: logcat (pid 1312)
            520K: healthd (pid 1303)
            493K: dumpsys (pid 5583)
            483K: dnsmasq (pid 1599)
            482K: servicemanager (pid 1307)
            470K: sh (pid 1311)
            442K: sh (pid 1518)
            435K: perfprofd (pid 1333)
            324K: ipv6proxy (pid 1569)
            277K: debuggerd (pid 1264)
            239K: debuggerd:signaller (pid 1267)
     67,985K: System
         67,985K: system (pid 1639)
     81,143K: Persistent
         60,472K: com.android.systemui (pid 1777 / activities)
         20,671K: com.android.phone (pid 1878)
     29,429K: Foreground
         29,429K: com.android.launcher3 (pid 2331 / activities)
     39,684K: Visible
         21,077K: com.android.inputmethod.latin (pid 1744)
         14,790K: cn.kidyn.qdmedical160:core (pid 4320)
          3,817K: android.ext.services (pid 2176)
     14,114K: A Services
         14,114K: cn.kidyn.qdmedical160:todaystep (pid 5236)
     90,764K: Previous
         85,517K: cn.kidyn.qdmedical160 (pid 4273 / activities)
          5,247K: com.android.providers.calendar (pid 5173)
     24,383K: B Services
         24,383K: cn.kidyn.qdmedical160:pushservice (pid 4466)
    121,414K: Cached
         58,943K: org.chromium.webview_shell (pid 3990 / activities)
         11,734K: android.process.acore (pid 2422)
         10,912K: com.android.packageinstaller (pid 3718)
         10,824K: com.android.quicksearchbox (pid 2386 / activities)
          6,249K: com.android.calendar (pid 5161)
          6,179K: com.android.deskclock (pid 2093)
          5,361K: com.android.gallery3d (pid 2539)
          3,999K: com.android.printspooler (pid 2285)
          3,848K: com.android.defcontainer (pid 2752)
          3,365K: com.svox.pico (pid 2781)

Total PSS by category:
    114,379K: Native
    100,052K: Dalvik
     64,802K: .dex mmap
     54,784K: .so mmap
     44,872K: .oat mmap
     41,614K: .apk mmap
     36,631K: Unknown
     32,520K: Ashmem
     30,866K: .art mmap
     14,411K: Other mmap
     14,162K: Dalvik Other
      9,460K: Stack
      2,019K: .ttf mmap
        501K: Other dev
        160K: .jar mmap
         28K: Cursor
          0K: Gfx dev
          0K: EGL mtrack
          0K: GL mtrack
          0K: Other mtrack

Total RAM: 1,550,644K (status normal)
 Free RAM: 1,036,918K (  121,414K cached pss +   499,892K cached kernel +   415,612K free)
 Used RAM:   514,515K (  439,847K used pss +    74,668K kernel)
 Lost RAM:      -789K
   Tuning: 384 (large 384), oom   184,320K, restore limit    61,440K (high-end-gfx)

3. 内存分析工具


参考资料


创作不易,你的「三连」是丑丑最大的动力,我们下次见!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章