首页 > 代码库 > Process Stats:了解你的APP怎样使用内存

Process Stats:了解你的APP怎样使用内存

原文地址:http://android-developers.blogspot.com/2014/01/process-stats-understanding-how-your.html?m=1

原作者:Dianne Hackborn, Android framework team

翻译:大苞米,http://blog.csdn.net/a396901990


Android 4.4 KitKat 提出了一个新系统服务,叫做procstats。它将帮助你更好的理解你的app是怎样使用内存资源的。Procstats能够去监视你app在一段时间的行为,包含在后台(background)执行了多久。并在此段时间使用了多少内存。

从而帮助你高速的找到应用中不效率和不规范的地方去避免影响其性能(performs),尤其是在低内存的设备上执行时。

你能够通过adb shell命令去使用procstats,或者更方便的方式是执行Process Stats开发人员工具,它提供了一个前端的图形应用去展示和命令行同样的数据(在4.4版本号的手机中点击Settings > Developer options > Process Stats)



查看全系统下的内存使用和后台进程(Looking at systemwide memory use and background processes)


例如以下图所看到的。当你打开Process Stats后。你能够看到一个在固定时间段内全系统内存使用情况和细节的简要分析。


技术分享

在屏幕的最上面我们能够看到:

●近期3.5小时内的数据统计
●当前的设备内存处于良好状态("Device memory is currently normal")

●在这一整段时间内内存状态处于优(绿色的状态条),假设内存越来越少的话你将看到黄色和红色的状态条代表在这段时间内处于低内存状态。


在绿色状态条以下。我们能够看到后台进程和内存载入的概况
右側的百分数表示:每一个进程所花费的时间占总时间的百分比
蓝色条表示:每个进程载入的相对内存计算(内存载入=runtime * vag_pss,后面会具体介绍)
在显示过程中。有些应用会列出来多次(比方,Google Play services运行了两条进程)。这些APP的内存载入值是对于每一个单独的进程的载入总数。


有一些进程在最上面的进程他们都相对总时间运行了100%。

可是他们有不同的比重,是由于相对内存使用的原因。



分析指定进程的内存(Analyzing memory for specific processes)


以下的样例展示了一些有趣的数据:
时钟APP相对于Google键盘消耗了很多其它的内存比重,即使它执行了更少的时间。

我们能够通过点击他们去查看很多其它的细节信息。
技术分享             技术分享

通过两个进程的细节展示揭示了:
为什么时钟在一直执行。由于当设备进入空暇状态时,它被用来当做屏保。
即使时钟进程仅仅执行了键盘进程的一半时间,可是它仍然十分明显的消耗了大量内存(接近3倍)。

这也是为什么时钟内存的比重更大的原因。

从根本来说。procstats提供了一个“内存使用”的规格。去展示程序在后台的内存使用情况。

类似与存储和数据使用规格但又不同于他们,由于内存更难去量化和測量(procstats使用了一些小花招做到了)。

为了去阐述測量内存使用的复杂性。以下考虑下与其相关的话题:任务管理器(task managers)



了解任务管理和他们的内存信息(Understanding task managers and their memory info)


Android一直deeply支持多任务处理(multitasking),这意味着我们希望有一个类似与传统桌面UI一样的用户图形界面,去控制这些多重任务。

然而对照桌面操作系统的多任务处理,Android中从根本上来说更加的复杂(在Multitasking the Android Way这篇文章中有介绍)。


多任务和持续进程管理

为了去体会在Android中进程管理有什么不同,你能够通过使用命令行:adb shell dumpsys activity,去看一下重要的系统服务和Activity Manager的输出信息。


以下的样例展示了当前应用进程(Android 4.4),并按重要程度排列:

ACTIVITY MANAGER RUNNING PROCESSES (dumpsys activity processes)
Process LRU list (sorted by oom_adj, 22 total, non-act at 2, non-svc at 2):
  PERS #21: sys   F/ /P  trm: 0 23064:system/1000 (fixed)
  PERS #20: pers  F/ /P  trm: 0 23163:com.android.systemui/u0a12 (fixed)
  PERS #19: pers  F/ /P  trm: 0 23344:com.nuance.xt9.input/u0a77 (fixed)
  PERS #18: pers  F/ /P  trm: 0 23357:com.android.phone/1001 (fixed)
  PERS #17: pers  F/ /P  trm: 0 23371:com.android.nfc/1027 (fixed)
  Proc # 3: fore  F/ /IB trm: 0 13892:com.google.android.apps.magazines/u0a59 (service)
    com.google.android.apps.magazines/com.google.apps.dots.android.app.service.SyncService<=Proc{23064:system/1000}
  Proc # 2: fore  F/ /IB trm: 0 23513:com.google.process.gapps/u0a8 (provider)
    com.google.android.gsf/.gservices.GservicesProvider<=Proc{13892:com.google.android.apps.magazines/u0a59}
  Proc # 0: fore  F/A/T  trm: 0 24811:com.android.settings/1000 (top-activity)
  Proc # 4: vis   F/ /IF trm: 0 23472:com.google.process.location/u0a8 (service)
    com.google.android.backup/.BackupTransportService<=Proc{23064:system/1000}
  Proc #14: prcp  F/ /IF trm: 0 23298:com.google.android.inputmethod.latin/u0a57 (service)
    com.google.android.inputmethod.latin/com.android.inputmethod.latin.LatinIME<=Proc{23064:system/1000}
  Proc # 1: home  B/ /HO trm: 0 23395:com.android.launcher/u0a13 (home)
  Proc #16: cch   B/ /CA trm: 0 23966:com.google.android.deskclock/u0a36 (cch-act)
  Proc # 6: cch   B/ /CE trm: 0 7716:com.google.android.music:main/u0a62 (cch-empty)
  Proc # 5: cch   B/ /CE trm: 0 8644:com.google.android.apps.docs/u0a39 (cch-empty)
  Proc # 8: cch+2 B/ /CE trm: 0 5131:com.google.android.youtube/u0a78 (cch-empty)
  Proc # 7: cch+2 B/ /CE trm: 0 23338:com.google.android.gms/u0a8 (cch-empty)
  Proc #10: cch+4 B/ /CE trm: 0 8937:com.google.android.apps.walletnfcrel/u0a24 (cch-empty)
  Proc # 9: cch+4 B/ /CE trm: 0 24689:com.google.android.apps.plus/u0a70 (cch-empty)
  Proc #15: cch+6 B/ /S  trm: 0 23767:com.google.android.apps.currents/u0a35 (cch-started-services)
  Proc #13: cch+6 B/ /CE trm: 0 9115:com.google.android.gm/u0a44 (cch-empty)
  Proc #12: cch+6 B/ /S  trm: 0 7738:android.process.media/u0a6 (cch-started-services)
  Proc #11: cch+6 B/ /CE trm: 0 8922:com.google.android.setupwizard/u0a19 (cch-empty)

dumpsys activity命令的输出信息,显示了全部如今正在执行的进程。

这里另一些重要的进程组——持久系统进程(persistent system processes),前台系统进程(foreground processes),后台系统进程(background processes)。终于缓存进程(finally cached processes)。

这些进程种类对于理解它是怎样影响系统是很重要的。

与此同一时候,进程列表是随时变化的。

比如:在上面样例中我们能够看到“com.google.android.gm”(Gmail) 是当前非常重要的进程,可是他是在后台同步执行。所以有些东西用户通常不会被告知或不想管理他。

每一个进程的内存使用
传统的任务管理器和内存使用息息相关。Android提供了一个工具叫做meminfo。使用它能够去查看当前每个进程的内存使用情况。

你能够通过命令行去运行它:adb shell dumpsys meminfo
以下是一个使用它输出的样例:

Total PSS by OOM adjustment:
    31841 kB: Native
               13173 kB: zygote (pid 23001)
                4372 kB: surfaceflinger (pid 23000)
                3721 kB: mediaserver (pid 126)
                3317 kB: glgps (pid 22993)
                1656 kB: drmserver (pid 125)
                 995 kB: wpa_supplicant (pid 23148)
                 786 kB: netd (pid 121)
                 518 kB: sdcard (pid 132)
                 475 kB: vold (pid 119)
                 458 kB: keystore (pid 128)
                 448 kB: /init (pid 1)
                 412 kB: adbd (pid 134)
                 254 kB: ueventd (pid 108)
                 238 kB: dhcpcd (pid 10617)
                 229 kB: tf_daemon (pid 130)
                 200 kB: installd (pid 127)
                 185 kB: dumpsys (pid 14207)
                 144 kB: healthd (pid 117)
                 139 kB: debuggerd (pid 122)
                 121 kB: servicemanager (pid 118)
    48217 kB: System
               48217 kB: system (pid 23064)
    49095 kB: Persistent
               34012 kB: com.android.systemui (pid 23163 / activities)
                7719 kB: com.android.phone (pid 23357)
                4676 kB: com.android.nfc (pid 23371)
                2688 kB: com.nuance.xt9.input (pid 23344)
    24945 kB: Foreground
               24945 kB: com.android.settings (pid 24811 / activities)
    17136 kB: Visible
               14026 kB: com.google.process.location (pid 23472)
                3110 kB: com.android.defcontainer (pid 13976)
     6911 kB: Perceptible
                6911 kB: com.google.android.inputmethod.latin (pid 23298)
    14277 kB: A Services
               14277 kB: com.google.process.gapps (pid 23513)
    26422 kB: Home
               26422 kB: com.android.launcher (pid 23395 / activities)
    21798 kB: B Services
               16242 kB: com.google.android.apps.currents (pid 23767)
                5556 kB: android.process.media (pid 7738)
   145869 kB: Cached
               41588 kB: com.google.android.apps.plus (pid 24689)
               21417 kB: com.google.android.deskclock (pid 23966 / activities)
               14463 kB: com.google.android.apps.docs (pid 8644)
               14303 kB: com.google.android.gm (pid 9115)
               11014 kB: com.google.android.music:main (pid 7716)
               10688 kB: com.google.android.apps.magazines (pid 13892)
               10240 kB: com.google.android.gms (pid 23338)
                9882 kB: com.google.android.youtube (pid 5131)
                8807 kB: com.google.android.apps.walletnfcrel (pid 8937)
                3467 kB: com.google.android.setupwizard (pid 8922)

Total RAM: 998096 kB
 Free RAM: 574945 kB (145869 cached pss + 393200 cached + 35876 free)
 Used RAM: 392334 kB (240642 used pss + 107196 buffers + 3856 shmem + 40640 slab)
 Lost RAM: 30817 kB
   Tuning: 64 (large 384), oom 122880 kB, restore limit 40960 kB (high-end-gfx)
dumpsys meminfo命令的输出样例,显示了当前正在执行的进程所使用的内存

我们正在看的和上面样例是同一个进程,而且也是按重要程度排序,不同的是这次有他们对内存影响。


通常当我们測量Android的使用内存时。我们使用Linux的PSS标准 (Proportional Set Size——实际物理内存)。
这是实际内存映射到进程中的数量,可是这个加权的的数量是在多个进程间共享的。

因此假设以4K内存每一页(page)映射到两个进程中的话,那么PPS的数量就是每条进程2K。

使用PSS的优点是你能够加入这个值到全部的进程中去决定实际的总共内存使用。这个特性被用在meminfo报告的最后,去计算使用(Used)了多少内存(这部分来自于非缓存进程),相反的是空暇(free)大小(包括了缓存进程)。


技术分享

任务管理器(Task-manager)样式的内存信息,展示在应用执行时的内存使用。


基于PSS的任务管理界面

当在设备上点击Settings > Apps > Running后能够显示任务管理器UI。

它显示了全部进程中执行的服务和系统状态。还计算了全部其它依赖进程的PPS内存。



此UI显示的都是即时的应用状态,而不是一段时间内的应用状态。由于在Android中,用户不能直接控制创建和清除应用进程。

这些进程可能为了以后使用而保持当前状态,或当系统决定后清除,或者当用户没有明白开启他们时在后台执行。


所以这仅仅是即时的内存使用状态。因此你可能会丢失在这一段时间内的一些重要信息。



比如,当我第一次查看进程状态时,能够看到com.google.android.apps.magazines进程在同步执行。可是就在我们搜集内存使用之后,它就不会在后台执行了。可是它仍然保持在旧的缓存进程中。

为了解决问题,就须要使用之前提过的procstats(它能够持续监视在一段时间内全部应用进程,从中收集PSS样品)。你能够通过命令行:adb shell dumpsys procstats去浏览procstats收集的原始数据

通过procstats查看一段时间内的内存使用
如今回到procstats,我们能够使用命令行:adb shell dumpsys procstats --hours 3  去输出最后3小时收集的内存信息。这些数据和之前图形界面的数据是同样的。
以下是全部进程在近期3小时内的输出数据。通过使用时间先后排序(在缓存状态下的进程不会计算在总时间排序中)。

我们如今清晰的看到在这段时间内执行着一个庞大的进程组,中间又会一些新的进程突然的执行——这里包含Magazines进程,我们能够看到他相对于总时间3小时执行了3.6%

* com.google.android.inputmethod.latin / u0a57:
           TOTAL: 100% (6.4MB-6.7MB-6.8MB/5.4MB-5.4MB-5.4MB over 21)
          Imp Fg: 100% (6.4MB-6.7MB-6.8MB/5.4MB-5.4MB-5.4MB over 21)
  * com.google.process.gapps / u0a8:
           TOTAL: 100% (12MB-13MB-14MB/10MB-11MB-12MB over 211)
          Imp Fg: 0.11%
          Imp Bg: 0.83% (13MB-13MB-13MB/11MB-11MB-11MB over 1)
         Service: 99% (12MB-13MB-14MB/10MB-11MB-12MB over 210)
  * com.android.systemui / u0a12:
           TOTAL: 100% (29MB-32MB-34MB/26MB-29MB-30MB over 21)
      Persistent: 100% (29MB-32MB-34MB/26MB-29MB-30MB over 21)
  * com.android.phone / 1001:
           TOTAL: 100% (6.5MB-7.1MB-7.6MB/5.4MB-5.9MB-6.4MB over 21)
      Persistent: 100% (6.5MB-7.1MB-7.6MB/5.4MB-5.9MB-6.4MB over 21)
  * com.nuance.xt9.input / u0a77:
           TOTAL: 100% (2.3MB-2.5MB-2.7MB/1.5MB-1.5MB-1.5MB over 21)
      Persistent: 100% (2.3MB-2.5MB-2.7MB/1.5MB-1.5MB-1.5MB over 21)
  * com.android.nfc / 1027:
           TOTAL: 100% (4.2MB-4.5MB-4.6MB/3.2MB-3.2MB-3.3MB over 21)
      Persistent: 100% (4.2MB-4.5MB-4.6MB/3.2MB-3.2MB-3.3MB over 21)
  * com.google.process.location / u0a8:
           TOTAL: 100% (13MB-13MB-14MB/10MB-11MB-11MB over 21)
          Imp Fg: 100% (13MB-13MB-14MB/10MB-11MB-11MB over 21)
  * system / 1000:
           TOTAL: 100% (42MB-46MB-56MB/39MB-42MB-48MB over 21)
      Persistent: 100% (42MB-46MB-56MB/39MB-42MB-48MB over 21)
  * com.google.android.apps.currents / u0a35:
           TOTAL: 100% (16MB-16MB-16MB/14MB-14MB-14MB over 17)
         Service: 100% (16MB-16MB-16MB/14MB-14MB-14MB over 17)
  * com.android.launcher / u0a13:
           TOTAL: 77% (25MB-26MB-27MB/22MB-23MB-24MB over 73)
             Top: 77% (25MB-26MB-27MB/22MB-23MB-24MB over 73)
          (Home): 23% (25MB-26MB-26MB/23MB-23MB-24MB over 12)
  * android.process.media / u0a6:
           TOTAL: 48% (5.0MB-5.3MB-5.5MB/4.0MB-4.2MB-4.2MB over 11)
          Imp Fg: 0.00%
          Imp Bg: 0.00%
         Service: 48% (5.0MB-5.3MB-5.5MB/4.0MB-4.2MB-4.2MB over 11)
        Receiver: 0.00%
        (Cached): 22% (4.1MB-4.5MB-4.8MB/3.0MB-3.5MB-3.8MB over 8)
  * com.google.android.deskclock / u0a36:
           TOTAL: 42% (20MB-21MB-21MB/18MB-19MB-19MB over 8)
          Imp Fg: 42% (20MB-21MB-21MB/18MB-19MB-19MB over 8)
         Service: 0.00%
        Receiver: 0.01%
        (Cached): 58% (17MB-20MB-21MB/16MB-18MB-19MB over 14)
  * com.android.settings / 1000:
           TOTAL: 23% (19MB-22MB-28MB/15MB-19MB-24MB over 31)
             Top: 23% (19MB-22MB-28MB/15MB-19MB-24MB over 31)
      (Last Act): 77% (9.7MB-14MB-20MB/7.5MB-11MB-18MB over 8)
        (Cached): 0.02%
  * com.google.android.apps.magazines / u0a59:
           TOTAL: 3.6% (10MB-10MB-10MB/8.7MB-9.0MB-9.0MB over 6)
          Imp Bg: 0.03%
         Service: 3.6% (10MB-10MB-10MB/8.7MB-9.0MB-9.0MB over 6)
        (Cached): 17% (9.9MB-10MB-10MB/8.7MB-8.9MB-9.0MB over 5)
  * com.android.defcontainer / u0a5:
           TOTAL: 1.4% (2.7MB-3.0MB-3.0MB/1.9MB-1.9MB-1.9MB over 7)
             Top: 1.2% (3.0MB-3.0MB-3.0MB/1.9MB-1.9MB-1.9MB over 6)
          Imp Fg: 0.19% (2.7MB-2.7MB-2.7MB/1.9MB-1.9MB-1.9MB over 1)
         Service: 0.00%
        (Cached): 15% (2.6MB-2.6MB-2.6MB/1.8MB-1.8MB-1.8MB over 1)
  * com.google.android.youtube / u0a78:
           TOTAL: 1.3% (9.0MB-9.0MB-9.0MB/7.8MB-7.8MB-7.8MB over 1)
          Imp Bg: 1.0% (9.0MB-9.0MB-9.0MB/7.8MB-7.8MB-7.8MB over 1)
         Service: 0.27%
      Service Rs: 0.01%
        Receiver: 0.00%
        (Cached): 99% (9.1MB-9.4MB-9.7MB/7.7MB-7.9MB-8.1MB over 24)
  * com.google.android.gms / u0a8:
           TOTAL: 0.91% (9.2MB-9.2MB-9.2MB/7.6MB-7.6MB-7.6MB over 1)
          Imp Bg: 0.79% (9.2MB-9.2MB-9.2MB/7.6MB-7.6MB-7.6MB over 1)
         Service: 0.11%
        Receiver: 0.00%
        (Cached): 99% (8.2MB-9.4MB-10MB/6.5MB-7.6MB-8.1MB over 25)
  * com.google.android.gm / u0a44:
           TOTAL: 0.56%
          Imp Bg: 0.55%
         Service: 0.01%
        Receiver: 0.00%
        (Cached): 99% (11MB-13MB-14MB/10MB-12MB-13MB over 24)
  * com.google.android.apps.plus / u0a70:
           TOTAL: 0.22%
          Imp Bg: 0.22%
         Service: 0.00%
        Receiver: 0.00%
        (Cached): 100% (38MB-40MB-41MB/36MB-38MB-39MB over 17)
  * com.google.android.apps.docs / u0a39:
           TOTAL: 0.15%
          Imp Bg: 0.09%
         Service: 0.06%
        (Cached): 54% (13MB-14MB-14MB/12MB-12MB-13MB over 17)
  * com.google.android.music:main / u0a62:
           TOTAL: 0.11%
          Imp Bg: 0.04%
         Service: 0.06%
        Receiver: 0.01%
        (Cached): 70% (7.7MB-10MB-11MB/6.4MB-9.0MB-9.3MB over 20)
  * com.google.android.apps.walletnfcrel / u0a24:
           TOTAL: 0.01%
        Receiver: 0.01%
        (Cached): 69% (8.1MB-8.4MB-8.6MB/7.0MB-7.1MB-7.1MB over 13)
  * com.google.android.setupwizard / u0a19:
           TOTAL: 0.00%
        Receiver: 0.00%
        (Cached): 69% (2.7MB-3.2MB-3.4MB/1.8MB-2.0MB-2.2MB over 13)

Run time Stats:
  SOff/Norm: +1h43m29s710ms
  SOn /Norm: +1h37m14s290ms
      TOTAL: +3h20m44s0ms

          Start time: 2013-11-06 07:24:27
  Total elapsed time: +3h42m23s56ms (partial) libdvm.so chromeview
 命令行:dumpsys procstats --hours 3的输出样例,显示近期3小时后台执行的进程内存细节。


这个百分比告诉你在总时间内各种状态下进程的消耗。

 内存值告知你在当前状态下的内存样本为minPss-avgPss-maxPss / minUss-avgUss-maxUssprocstats 工具有一组命令行选项去控制输出结果——使用:adb shell dumpsys procstats -h查看可运行选项列表。

对照这些从procstats得到的原数据我们能够看到。进程会在以下的几种状态中执行 Imp Fg, Imp Bg, Service, Service Rs, and Receiver

在这些情况下。进程会活跃的执行在后台中。仅仅要它完毕它须要做的工作。在设备使用内存时。这些进程状态最easy引起以下这个问题问题:应用在后台执行时,内存从事其它工作。



開始使用procstats(Getting started with procstats


我们已经找到新的procstats工具去了解总体内存在Android系统中的行为。

这也是Android4.4的project减肥计划(Project Svelte)的重要部分之中的一个。


在开发你自己的应用时,一定要使用procstats和刚才提到的其它工具去帮助你了解APP的表现。特别是他在后台执行的时间和使用的内存。


很多其它关于Android怎样去分析和调试内存的内容,能够看developer站点中的这篇文章: Investigating Your RAM Usage .



写在最后:


我想写一篇关于Android内存优化的一篇文章,刚好须要procstats和meninfo这方面的内容,于是搜到了这篇文章。

因为引用了当中的非常多内容并且发现国内没有相关的资料,所以索性直接翻译了它。


这是第一次翻译技术类英文文章,才知道这并非一件easy的事。最開始採用了英文直译。译完以后发现根本读不通,之后在直译基础上又意译了一遍,但仍旧有一些地方比較难读,主要原因应该是我对内存方面的知识理解能力有限吧。


假设大家反映都还行的话,以后有时间我会把本文中引用的几个链接文章也翻译一下。

Process Stats:了解你的APP怎样使用内存