1. 程式人生 > >Process Stats:了解你的APP怎樣使用內存

Process Stats:了解你的APP怎樣使用內存

-h service prop 固定 gravity stand 狀態 單獨 做到

原文地址: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怎樣使用內存