dumpsys
這項工具是在 Android 裝置上執行,可提供系統服務相關資訊。您可以使用 Android Debug Bridge (ADB) 透過指令列呼叫 dumpsys
,取得在連線裝置上執行的所有系統服務的診斷輸出內容。產生的輸出內容通常比您想要的程度來得多,因此請使用以下指令列選項,只取得您感興趣的系統服務輸出內容。本頁也會說明如何使用 dumpsys
完成常見工作,例如檢查輸入、RAM、電池或網路診斷。
語法
使用 dumpsys
的一般語法如下:
adb shell dumpsys [-t timeout] [--help | -l | --skip services | service [arguments] | -c | -h]
如要針對連線裝置的所有系統服務取得診斷輸出,只要執行 adb shell dumpsys
即可。無論如何,產生的結果量將比您預期的要多。如需更易於管理的輸出,請在指令中加入服務,藉此指定要檢查的服務。舉例來說,以下指令提供輸入元件 (例如觸控螢幕或內建鍵盤) 的系統資料:
adb shell dumpsys input
如需可與 dumpsys
搭配使用的系統服務完整清單,請使用下列指令:
adb shell dumpsys -l
指令列選項
下表列出使用 dumpsys
時可用選項。
選項 | 說明 |
---|---|
-t timeout
|
指定逾時期間(以秒為單位)。如未指定,預設值為 10 秒。 |
--help
|
列印 dumpsys 工具的說明文字。 |
-l
|
輸出可搭配 dumpsys 使用的完整系統服務清單。 |
--skip services
|
指定您不想包含在輸出內容中的 services。 |
service [arguments]
|
指定您要輸出的 service。有些服務可讓您傳遞選用 arguments。您可以透過下列方式傳送 -h 選項給服務,以瞭解這些選用引數:adb shell dumpsys procstats -h |
-c
|
指定特定服務時,請附加這個選項,以適合機器的格式輸出資料。 |
-h
|
附加特定服務的選項,即可查看相關說明文字和該服務的其他選項。 |
檢查輸入診斷資料
如下方所示,指定 input
服務會傾印系統輸入裝置的狀態,例如鍵盤和觸控螢幕,以及處理輸入事件。
adb shell dumpsys input
輸出結果會因在連線裝置上執行的 Android 版本而有所不同。以下各節說明您一般會看到的資訊類型。
事件中心狀態
以下為檢查輸入診斷「事件狀態」時可能看到的示例:
INPUT MANAGER (dumpsys input) Event Hub State: BuiltInKeyboardId: -2 Devices: -1: Virtual Classes: 0x40000023 Path:Descriptor: a718a782d34bc767f4689c232d64d527998ea7fd Location: ControllerNumber: 0 UniqueId: Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000 KeyLayoutFile: /system/usr/keylayout/Generic.kl KeyCharacterMapFile: /system/usr/keychars/Virtual.kcm ConfigurationFile: HaveKeyboardLayoutOverlay: false 1: msm8974-taiko-mtp-snd-card Headset Jack Classes: 0x00000080 Path: /dev/input/event5 Descriptor: c8e3782483b4837ead6602e20483c46ff801112c Location: ALSA ControllerNumber: 0 UniqueId: Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000 KeyLayoutFile: KeyCharacterMapFile: ConfigurationFile: HaveKeyboardLayoutOverlay: false 2: msm8974-taiko-mtp-snd-card Button Jack Classes: 0x00000001 Path: /dev/input/event4 Descriptor: 96fe62b244c555351ec576b282232e787fb42bab Location: ALSA ControllerNumber: 0 UniqueId: Identifier: bus=0x0000, vendor=0x0000, product=0x0000, version=0x0000 KeyLayoutFile: /system/usr/keylayout/msm8974-taiko-mtp-snd-card_Button_Jack.kl KeyCharacterMapFile: /system/usr/keychars/msm8974-taiko-mtp-snd-card_Button_Jack.kcm ConfigurationFile: HaveKeyboardLayoutOverlay: false 3: hs_detect Classes: 0x00000081 Path: /dev/input/event3 Descriptor: 485d69228e24f5e46da1598745890b214130dbc4 Location: ControllerNumber: 0 UniqueId: Identifier: bus=0x0000, vendor=0x0001, product=0x0001, version=0x0001 KeyLayoutFile: /system/usr/keylayout/hs_detect.kl KeyCharacterMapFile: /system/usr/keychars/hs_detect.kcm ConfigurationFile: HaveKeyboardLayoutOverlay: false ...
輸入閱讀器狀態
InputReader
負責將核心解碼的輸入事件解碼。其狀態傾印會顯示每部輸入裝置的設定方式,以及近期發生的狀態變更,例如按下按鍵或輕觸觸控螢幕。
以下範例顯示觸控螢幕的輸出結果。記下裝置的解析度和使用的校正參數。
Input Reader State ... Device 6: Melfas MMSxxx Touchscreen IsExternal: false Sources: 0x00001002 KeyboardType: 0 Motion Ranges: X: source=0x00001002, min=0.000, max=719.001, flat=0.000, fuzz=0.999 Y: source=0x00001002, min=0.000, max=1279.001, flat=0.000, fuzz=0.999 PRESSURE: source=0x00001002, min=0.000, max=1.000, flat=0.000, fuzz=0.000 SIZE: source=0x00001002, min=0.000, max=1.000, flat=0.000, fuzz=0.000 TOUCH_MAJOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000 TOUCH_MINOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000 TOOL_MAJOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000 TOOL_MINOR: source=0x00001002, min=0.000, max=1468.605, flat=0.000, fuzz=0.000 Touch Input Mapper: Parameters: GestureMode: spots DeviceType: touchScreen AssociatedDisplay: id=0, isExternal=false OrientationAware: true Raw Touch Axes: X: min=0, max=720, flat=0, fuzz=0, resolution=0 Y: min=0, max=1280, flat=0, fuzz=0, resolution=0 Pressure: min=0, max=255, flat=0, fuzz=0, resolution=0 TouchMajor: min=0, max=30, flat=0, fuzz=0, resolution=0 TouchMinor: unknown range ToolMajor: unknown range ToolMinor: unknown range Orientation: unknown range Distance: unknown range TiltX: unknown range TiltY: unknown range TrackingId: min=0, max=65535, flat=0, fuzz=0, resolution=0 Slot: min=0, max=9, flat=0, fuzz=0, resolution=0 Calibration: touch.size.calibration: diameter touch.size.scale: 10.000 touch.size.bias: 0.000 touch.size.isSummed: false touch.pressure.calibration: amplitude touch.pressure.scale: 0.005 touch.orientation.calibration: none touch.distance.calibration: none SurfaceWidth: 720px SurfaceHeight: 1280px SurfaceOrientation: 0 Translation and Scaling Factors: XScale: 0.999 YScale: 0.999 XPrecision: 1.001 YPrecision: 1.001 GeometricScale: 0.999 PressureScale: 0.005 SizeScale: 0.033 OrientationCenter: 0.000 OrientationScale: 0.000 DistanceScale: 0.000 HaveTilt: false TiltXCenter: 0.000 TiltXScale: 0.000 TiltYCenter: 0.000 TiltYScale: 0.000 Last Button State: 0x00000000 Last Raw Touch: pointerCount=0 Last Cooked Touch: pointerCount=0
輸入讀取器狀態傾印結束時,有一些全域設定參數的相關資訊,例如輕觸間隔。
Configuration: ExcludedDeviceNames: [] VirtualKeyQuietTime: 0.0ms PointerVelocityControlParameters: scale=1.000, lowThreshold=500.000, highThreshold=3000.000, acceleration=3.000 WheelVelocityControlParameters: scale=1.000, lowThreshold=15.000, highThreshold=50.000, acceleration=4.000 PointerGesture: Enabled: true QuietInterval: 100.0ms DragMinSwitchSpeed: 50.0px/s TapInterval: 150.0ms TapDragInterval: 300.0ms TapSlop: 20.0px MultitouchSettleInterval: 100.0ms MultitouchMinDistance: 15.0px SwipeTransitionAngleCosine: 0.3 SwipeMaxWidthRatio: 0.2 MovementSpeedRatio: 0.8 ZoomSpeedRatio: 0.3
輸入調度工具狀態
InputDispatcher
負責將輸入事件傳送至應用程式。如下方的範例輸出所示,其狀態傾印顯示正在處理的視窗、輸入佇列的狀態,以及 ANR 進行中的進度等資訊。
Input Dispatcher State: DispatchEnabled: 1 DispatchFrozen: 0 FocusedApplication: <null> FocusedWindow: name='Window{3fb06dc3 u0 StatusBar}' TouchStates: <no displays touched> Windows: 0: name='Window{357bbbfe u0 SearchPanel}', displayId=0, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x01820100, type=0x000007e8, layer=211000, frame=[0,0][1080,1920], scale=1.000000, touchableRegion=[0,0][1080,1920], inputFeatures=0x00000000, ownerPid=22674, ownerUid=10020, dispatchingTimeout=5000.000ms 1: name='Window{3b14c0ca u0 NavigationBar}', displayId=0, paused=false, hasFocus=false, hasWallpaper=false, visible=false, canReceiveKeys=false, flags=0x01840068, type=0x000007e3, layer=201000, frame=[0,1776][1080,1920], scale=1.000000, touchableRegion=[0,1776][1080,1920], inputFeatures=0x00000000, ownerPid=22674, ownerUid=10020, dispatchingTimeout=5000.000ms 2: name='Window{2c7e849c u0 com.vito.lux}', displayId=0, paused=false, hasFocus=false, hasWallpaper=false, visible=true, canReceiveKeys=false, flags=0x0089031a, type=0x000007d6, layer=191000, frame=[-495,-147][1575,1923], scale=1.000000, touchableRegion=[-495,-147][1575,1923], inputFeatures=0x00000000, ownerPid=4697, ownerUid=10084, dispatchingTimeout=5000.000ms ... MonitoringChannels: 0: 'WindowManager (server)' RecentQueue: length=10 MotionEvent(deviceId=4, source=0x00001002, action=2, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, displayId=0, pointers=[0: (335.0, 1465.0)]), policyFlags=0x62000000, age=217264.0ms MotionEvent(deviceId=4, source=0x00001002, action=1, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, displayId=0, pointers=[0: (335.0, 1465.0)]), policyFlags=0x62000000, age=217255.7ms MotionEvent(deviceId=4, source=0x00001002, action=0, flags=0x00000000, metaState=0x00000000, buttonState=0x00000000, edgeFlags=0x00000000, xPrecision=1.0, yPrecision=1.0, displayId=0, pointers=[0: (330.0, 1283.0)]), policyFlags=0x62000000, age=216805.0ms ... PendingEvent: <none> InboundQueue: <empty> ReplacedKeys: <empty> Connections: 0: channelName='WindowManager (server)', windowName='monitor', status=NORMAL, monitor=true, inputPublisherBlocked=false OutboundQueue: <empty> WaitQueue: <empty> 1: channelName='278c1d65 KeyguardScrim (server)', windowName='Window{278c1d65 u0 KeyguardScrim}', status=NORMAL, monitor=false, inputPublisherBlocked=false OutboundQueue: <empty> WaitQueue: <empty> 2: channelName='357bbbfe SearchPanel (server)', windowName='Window{357bbbfe u0 SearchPanel}', status=NORMAL, monitor=false, inputPublisherBlocked=false OutboundQueue: <empty> WaitQueue: <empty> ... AppSwitch: not pending 7: channelName='2280455f com.google.android.gm/com.google.android.gm.ConversationListActivityGmail (server)', windowName='Window{2280455f u0 com.google.android.gm/com.google.android.gm.ConversationListActivityGmail}', status=NORMAL, monitor=false, inputPublisherBlocked=false OutboundQueue: <empty> WaitQueue: <empty> 8: channelName='1a7be08a com.android.systemui/com.android.systemui.recents.RecentsActivity (server)', windowName='Window{1a7be08a u0 com.android.systemui/com.android.systemui.recents.RecentsActivity EXITING}', status=NORMAL, monitor=false, inputPublisherBlocked=false OutboundQueue: <empty> WaitQueue: <empty> 9: channelName='3b14c0ca NavigationBar (server)', windowName='Window{3b14c0ca u0 NavigationBar}', status=NORMAL, monitor=false, inputPublisherBlocked=false OutboundQueue: <empty> WaitQueue: <empty> ... Configuration: KeyRepeatDelay: 50.0ms KeyRepeatTimeout: 500.0ms
檢查重點
檢查 input
服務的各種輸出內容時,請注意以下幾點:
事件中心狀態:
- 系統會顯示您預期的所有輸入裝置。
- 每部輸入裝置都有合適的金鑰版面配置檔案、金鑰字元對應檔案和輸入裝置設定設定檔。如果檔案缺失或含有語法錯誤,系統就不會載入這些檔案。
- 每部輸入裝置都已正確分類。
Classes
檔案中的位元會對應到EventHub.h
中的旗標,例如INPUT_DEVICE_CLASS_TOUCH_MT
。 -
BuiltInKeyboardId
是正確的。如果裝置沒有內建鍵盤,則 ID 必須是-2
。否則,這個值應為內建鍵盤的 ID。 - 若發現
BuiltInKeyboardId
非-2
在這個情況下,您應該會在某處找到特殊函式撥號鍵盤所需的遺漏的機碼對應檔。特殊函式鍵盤裝置應含有僅包含type SPECIAL_FUNCTION
行的關鍵金鑰對應檔案 (也就是我們在前述的tuna-gpio-keykad.kcm
檔案中看見的內容)。
輸入閱讀器狀態:
- 畫面上會顯示現在所有預期的輸入裝置。
- 每部輸入裝置設定皆正確無誤。請特別留意觸控螢幕和搖桿是否正確無誤。
輸入調度工具狀態:
- 所有輸入事件都會如預期照常處理。
- 同時輕觸觸控螢幕並執行
dumpsys
後,TouchStates
行可正確識別您正觸控的視窗。
測試 UI 效能
指定 gfxinfo
服務可為輸出提供與錄製階段中發生的動畫頁框相關的效能資訊。下列指令使用 gfxinfo
收集特定套件名稱的 UI 效能資料:
adb shell dumpsys gfxinfo package-name
您也可以加入 framestats
選項,提供更詳細的影格時間資訊,從最近的頁框擷取更多資訊,協助您更準確地追蹤問題並進行除錯,如下所示:
adb shell dumpsys gfxinfo package-name framestats
想要進一步瞭解如何使用 gfxinfo
和 framestats
將 UI 效能測量結果整合至測試做法,請參閱編寫 Macrobenchmark。
檢查網路診斷
指定 netstats
服務後,您就能取得上次啟動裝置後收集到的網路使用統計資料。如要輸出其他資訊 (例如詳細的不重複使用者 ID (UID) 資訊),請加入 detail
選項,如下所示:
adb shell dumpsys netstats detail
輸出結果會因在連線裝置上執行的 Android 版本而有所不同。以下各節說明您一般會看到的資訊類型。
使用中的介面和有效的 UID 介面
下列範例輸出會列出已連線裝置的有效介面和有效的 UID 介面。在多數情況下,使用中的介面和使用中的 UID 介面都是相同的。
Active interfaces: iface=wlan0 ident=[{type=WIFI, subType=COMBINED, networkId="Guest"}] Active UID interfaces: iface=wlan0 ident=[{type=WIFI, subType=COMBINED, networkId="Guest"}]
「Dev」和「Xt」統計資料
以下是開發人員統計資料部分的輸出範例:
Dev stats: Pending bytes: 1798112 History since boot: ident=[{type=WIFI, subType=COMBINED, networkId="Guest", metered=false}] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600 st=1497891600 rb=1220280 rp=1573 tb=309870 tp=1271 op=0 st=1497895200 rb=29733 rp=145 tb=85354 tp=185 op=0 st=1497898800 rb=46784 rp=162 tb=42531 tp=192 op=0 st=1497902400 rb=27570 rp=111 tb=35990 tp=121 op=0 Xt stats: Pending bytes: 1771782 History since boot: ident=[{type=WIFI, subType=COMBINED, networkId="Guest", metered=false}] uid=-1 set=ALL tag=0x0 NetworkStatsHistory: bucketDuration=3600 st=1497891600 rb=1219598 rp=1557 tb=291628 tp=1255 op=0 st=1497895200 rb=29623 rp=142 tb=82699 tp=182 op=0 st=1497898800 rb=46684 rp=160 tb=39756 tp=191 op=0 st=1497902400 rb=27528 rp=110 tb=34266 tp=120 op=0
UID 統計資料
以下是每個 UID 的詳細統計資料範例。
UID stats: Pending bytes: 744 Complete history: ident=[[type=MOBILE_SUPL, subType=COMBINED, subscriberId=311111...], [type=MOBILE, subType=COMBINED, subscriberId=311111...]] uid=10007 set=DEFAULT tag=0x0 NetworkStatsHistory: bucketDuration=7200000 bucketStart=1406167200000 activeTime=7200000 rxBytes=4666 rxPackets=7 txBytes=1597 txPackets=10 operations=0 ident=[[type=WIFI, subType=COMBINED, networkId="MySSID"]] uid=10007 set=DEFAULT tag=0x0 NetworkStatsHistory: bucketDuration=7200000 bucketStart=1406138400000 activeTime=7200000 rxBytes=17086802 rxPackets=15387 txBytes=1214969 txPackets=8036 operations=28 bucketStart=1406145600000 activeTime=7200000 rxBytes=2396424 rxPackets=2946 txBytes=464372 txPackets=2609 operations=70 bucketStart=1406152800000 activeTime=7200000 rxBytes=200907 rxPackets=606 txBytes=187418 txPackets=739 operations=0 bucketStart=1406160000000 activeTime=7200000 rxBytes=826017 rxPackets=1126 txBytes=267342 txPackets=1175 operations=35
如要找出應用程式的 UID,請執行下列指令:adb shell dumpsys
package your-package-name
。然後找出標有 userId
的行。
舉例來說,如要找出「com.example.myapp」應用程式的網路用量,請執行下列指令:
adb shell dumpsys package com.example.myapp | grep userId
畫面會顯示類似以下的輸出內容:
userId=10007 gids=[3003, 1028, 1015]
使用上方的範例傾印資料,找出含有 uid=10007
的行。有兩行,第一行代表行動網路連線,第二行代表 Wi-Fi 連線。在每一行的下方,您可以看到每兩小時視窗 (bucketDuration
以毫秒為單位) 的資訊:
-
set=DEFAULT
表示前景網路用量,set=BACKGROUND
則表示背景用量。set=ALL
表示兩者。 -
tag=0x0
表示與流量相關聯的通訊端標記。 -
rxBytes
和rxPackets
代表對應時間間隔內接收的位元組數和收到的封包。 -
txBytes
和txPackets
代表在對應的時間間隔內傳送 (已傳送) 位元組和已傳送封包。
檢查電池診斷
指定 batterystats
服務後,系統會根據裝置專屬 ID (UID) 整理裝置電池用量的相關統計資料。如要瞭解如何使用 dumpsys
測試應用程式的 Doze 和 App Standby,請參閱使用 Doze 和 App Standby 進行測試。
batterystats
的指令如下:
adb shell dumpsys batterystats options
如要查看 batterystats
可用的其他選項,請納入 -h
選項。以下範例顯示自裝置上次充電後,指定的應用程式套件的電池用量統計資料:
adb shell dumpsys batterystats --charged package-name
輸出結果通常包含以下內容:
- 電池相關事件記錄
- 裝置的全域統計資料
- 每個 UID 和系統元件的概略耗電量
- 每個封包每個應用程式的行動毫秒數
- 系統 UID 匯總統計資料
- 應用程式 UID 匯總統計資料
進一步瞭解如何使用batterystats
並產生輸出的 HTML 視覺呈現,方便您輕鬆瞭解及診斷電池相關問題,閱讀使用 Batterystats 和 Battery Historian 設定檔剖析電池用量。
檢查機器友善輸出
您可以使用下列指令,以機器可讀取的 CSV 格式產生 batterystats
輸出:
adb shell dumpsys batterystats --checkin
以下是您會看到的輸出範例:
9,0,i,vers,11,116,K,L 9,0,i,uid,1000,android 9,0,i,uid,1000,com.android.providers.settings 9,0,i,uid,1000,com.android.inputdevices 9,0,i,uid,1000,com.android.server.telecom ... 9,0,i,dsd,1820451,97,s-,p- 9,0,i,dsd,3517481,98,s-,p- 9,0,l,bt,0,8548446,1000983,8566645,1019182,1418672206045,8541652,994188 9,0,l,gn,0,0,666932,495312,0,0,2104,1444 9,0,l,m,6794,0,8548446,8548446,0,0,0,666932,495312,0,697728,0,0,0,5797,0,0 ...
電池用量觀察結果可能是每個 UID 或系統層級的結果;系統會根據資料在分析電池效能的實用程度下選擇納入資料。每列代表一個觀察項目,其中包含下列元素:
- 預留位置整數
- 與觀察項目相關聯的使用者 ID
- 匯總模式:
- 「i」表示未收費/未充電狀態的相關資訊。
- 「l」代表 --charged (自上次扣款後使用情形)。
- 「u」代表 --unplugged (自上次解開後至今的用量)。將在 Android 5.1.1 版中淘汰。
- 區段 ID:決定如何解譯行中的後續值。
下表說明各種可能出現的區段 ID:
版面 ID | 說明 | 其餘欄位 |
---|---|---|
版本 |
版本 |
簽到版本、包裹版本、啟動平台版本、結束平台版本 |
uid |
UID |
uid、套件名稱 |
apk |
APK |
喚醒, APK, 服務, 開始時間, 啟動, 啟動 |
pr |
程序 |
程序, 使用者, 系統, 前景, 開始 |
sr |
感應器 |
感應器號碼, 時間, 計數 |
vib |
振子 |
時間、數量 |
fg |
前景 |
時間、數量 |
st |
狀態時間 |
前景, 啟用, 執行中 |
wl |
Wake Lock |
喚醒鎖定, 全時, f, 完整計數, 部分, p, 部分計數, 視窗時間, w, 視窗數量 |
sy |
同步處理 |
同步處理, 時間, 計數 |
jb |
工作 |
工作, 時間, 數量 |
kwl |
核心 Wake Lock |
核心 Wake Lock, 時間, 數量 |
wr |
喚醒原因 |
喚醒原因, 時間, 數量 |
nt |
網路 |
行動位元組 RX, 行動位元組 TX, Wi-Fi 位元組 RX, Wi-Fi 位元組 TX, 行動封包 RX, 行動封包 TX, Wi-Fi 封包 RX, Wi-Fi 封包 TX, 行動裝置使用時間, 使用中行動裝置計數 |
ua |
使用者活動 |
其他, 按鈕, 觸控 |
bt |
電池 |
開始計數, 電池即時, 電池運作時間, 即時總數, 總運作時間, 開始時間, 電池螢幕關閉, 螢幕關閉時間 |
dc |
電池放電 |
低, 高, 螢幕開啟, 螢幕關閉 |
lv |
電量 |
起始層級, 目前等級 |
wfl |
Wi-Fi |
所有 Wi-Fi 鎖定時間, Wi-Fi 掃描時間, Wi-Fi 執行時間, Wi-Fi 掃描次數, Wi-Fi 閒置時間, Wi-Fi 接收時間, Wi-Fi 傳輸時間 |
gwFL |
全球 Wi-Fi |
Wi-Fi 開啟時間, Wi-Fi 執行時間, Wi-Fi 閒置時間, Wi-Fi 接收時間, Wi-Fi 傳輸時間, Wi-Fi 電源 (mAh) |
糖 |
全域藍牙 |
BT 閒置時間, BT 接收時間, BT 傳送時間, BT 電源 (mAh) |
分 |
其他 |
螢幕開啟時間, 電話開啟時間, 完全喚醒鎖總時間, 部分喚醒鎖總時間, 行動無線電作用中時間, 行動無線電作用中調整時間, 互動時間, 省電模式啟用時間, 連線能力變化, 裝置空閒模式啟用時間, 裝置空閒模式啟用計數, 裝置空閒時間, 裝置空閒計數, 作用中行動無線電計數, 作用中行動無線電未知時間 |
gn |
全球網路 |
行動 RX 總位元組, 行動裝置 TX 總位元組數, Wi-Fi RX 總位元組數, Wi-Fi TX 總封包數, 行動 RX 封包總數, 行動裝置 TX 封包總數, Wi-Fi RX 封包總數, Wi-Fi TX 封包總數 |
br |
螢幕亮度 |
深色, 調暗, 中, 輕度, 亮 |
標準 |
訊號掃描時間 |
訊號掃描時間 |
sgt |
訊號強度強度 |
無, 不佳, 普通, 好, 很不錯 |
sgc |
訊號強度數 |
無, 不佳, 普通, 好, 很不錯 |
dct |
數據連線時間 |
無, GPRS, EDGE, UMTS, CDMA, EVDO_0, EVDO_A, 1xRTT, HSDPA, HSUPA, HSPA, IDEN, EVDO_B, LTE, EHRPD, HSPAP 等 |
DCC |
數據連線數量 |
無, GPRS, EDGE, UMTS, CDMA, EVDO_0, EVDO_A, 1xRTT, HSDPA, HSUPA, HSPA, IDEN, EVDO_B, LTE, EHRPD, HSPAP 等 |
wst |
Wi-Fi 狀態時間 |
關閉, 關閉掃描功能, 沒有網路, 中斷連線, 連結 STA, 連結 P2P, 連結 STA P2P, soft AP |
wsc |
Wi-Fi 狀態數量 |
關閉, 關閉掃描功能, 沒有網路, 中斷連線, 連結 STA, 連結 P2P, 連結 STA P2P, soft AP |
wsst |
Wi-Fi 供應狀態時間 |
無效, 中斷連線, 介面已停用, 已停用, 掃描, 驗證, 關聯, 相關聯, 四向交握, 群組交握, 已完成, 停滯, 未初始化 |
wssc |
Wi-Fi 供應鏈狀態 |
無效, 中斷連線, 介面已停用, 已停用, 掃描, 驗證, 關聯, 相關聯, 四向交握, 群組交握, 已完成, 停滯, 未初始化 |
wsgt |
Wi-Fi 訊號強度 |
無, 不佳, 普通, 好, 很不錯 |
wsgc |
Wi-Fi 訊號強度 |
無, 不佳, 普通, 好, 很不錯 |
bst |
藍牙狀態時間 |
無效、低、中、高 |
bsc |
藍牙狀態數量 |
無效、低、中、高 |
pws |
用電量摘要 |
電池容量, 運算功率, 最低耗電量, 最大耗電量 |
pwi |
電力使用物品 |
標籤, mAh |
dsd |
放電步驟 |
時間長度、等級、螢幕、省電功能 |
csd |
充電步驟 |
時間長度、等級、螢幕、省電功能 |
dtr |
剩餘放電時間 |
剩餘電量 |
ctr |
剩餘充電時間 |
剩餘充電時間 |
注意:對於 Android 6.0 以下版本,m (Misc) 區段類別會追蹤藍牙無線電、行動網路無線電和 Wi-Fi 的電力使用情形。在 Android 6.0 以上版本中,系統會使用 pwi (電源用量項目) 部分搭配個別標籤 (wifi, blue, cell) 追蹤這些元件的電力使用情形。
查看記憶體配置
您可以透過下列兩種方式檢查應用程式的記憶體用量:在特定期間使用 procstats
,或是使用 meminfo
在特定時間建立快照。以下各節說明如何使用這兩種方法。
追蹤記錄
procstats
可讓您瞭解應用程式長期下來的行為,包括應用程式在背景執行的時間長度,以及在該時間範圍內的記憶體用量。
這項工具可協助您快速找到應用程式中的效率低落和不當行為 (例如記憶體流失),影響應用程式效能,特別是在低記憶體裝置上執行時。其狀態傾印會顯示每個應用程式的執行階段、比例集大小 (PSS)、不重複的集大小 (USS) 和常設集大小 (RSS) 等統計資料。
如要取得過去三小時的應用程式記憶體用量統計資料,請使用使用者可理解的格式,執行下列指令:
adb shell dumpsys procstats --hours 3
如下方範例所示,輸出結果會顯示應用程式執行的時間百分比,以及 PSS、USS 和 RSS 會顯示為minPSS-avgPSS-maxPSS/minUSS-avgUSS-maxUSS/minRSS-avgRSS-maxRSS
樣本數。
AGGREGATED OVER LAST 3 HOURS: * com.android.systemui / u0a37 / v28: TOTAL: 100% (15MB-16MB-17MB/7.7MB-8.7MB-9.4MB/7.7MB-9.6MB-84MB over 178) Persistent: 100% (15MB-16MB-17MB/7.7MB-8.7MB-9.4MB/7.7MB-9.6MB-84MB over 178) * com.android.se / 1068 / v28: TOTAL: 100% (2.8MB-2.9MB-2.9MB/300KB-301KB-304KB/304KB-22MB-33MB over 3) Persistent: 100% (2.8MB-2.9MB-2.9MB/300KB-301KB-304KB/304KB-22MB-33MB over 3) * com.google.android.gms.persistent / u0a7 / v19056073: TOTAL: 100% (37MB-38MB-40MB/27MB-28MB-29MB/124MB-125MB-126MB over 2) Imp Fg: 100% (37MB-38MB-40MB/27MB-28MB-29MB/124MB-125MB-126MB over 2) ... * com.android.gallery3d / u0a62 / v40030: TOTAL: 0.01% Receiver: 0.01% (Cached): 54% (6.4MB-6.5MB-6.9MB/4.4MB-4.4MB-4.4MB/4.4MB-26MB-68MB over 6) * com.google.android.tvlauncher / u0a30 / v1010900130: TOTAL: 0.01% Receiver: 0.01% (Cached): 91% (5.8MB-13MB-14MB/3.5MB-10MB-12MB/12MB-33MB-78MB over 6) * com.android.vending:instant_app_installer / u0a16 / v81633968: TOTAL: 0.01% Receiver: 0.01% (Cached): 100% (14MB-15MB-16MB/3.8MB-4.2MB-5.1MB/3.8MB-30MB-95MB over 7) ... Run time Stats: SOff/Norm: +32m52s226ms SOn /Norm: +2h10m8s364ms Mod : +17s930ms TOTAL: +2h43m18s520ms Memory usage: Kernel : 265MB (38 samples) Native : 73MB (38 samples) Persist: 262MB (90 samples) Top : 190MB (325 samples) ImpFg : 204MB (569 samples) ImpBg : 754KB (345 samples) Service: 93MB (1912 samples) Receivr: 227KB (1169 samples) Home : 66MB (12 samples) LastAct: 30MB (255 samples) CchAct : 220MB (450 samples) CchCAct: 193MB (71 samples) CchEmty: 182MB (652 samples) Cached : 58MB (38 samples) Free : 60MB (38 samples) TOTAL : 1.9GB ServRst: 50KB (278 samples) Start time: 2015-04-08 13:44:18 Total elapsed time: +2h43m18s521ms (partial) libart.so
meminfo
您可以使用下列指令來記錄應用程式記憶體分割於不同 RAM 分配方式的快照:
adb shell dumpsys meminfo package_name|pid [-d]
-d 旗標會列印關於 Dalvik 和 ART 記憶體用量的詳細資訊。
輸出結果會列出應用程式目前的所有配置情形 (以 KB 為單位)。
檢查這類資訊時,您應該熟悉下列類型的分配方式:
- 私有(乾淨頁與臟頁)RAM
- 請注意,這項資料僅有你處理的程序。這是系統在應用程式遭到銷毀時恢復的大量 RAM。一般來說,這個環節最重要的部分是 Private Dirty RAM。這是最昂貴的記憶體,因為它只會用於您的程序,其內容只會儲存於 RAM 中,所以無法改成指向儲存空間 (因為 Android 不會使用替換功能)。您製作的 Dalvik 和原生堆積分配量為 Private Dirty RAM;與 Zygote 程序共用的 Dalvik 和原生分配是 Shared Dirty RAM。
- 比例集大小 (PSS)
- 這是應用程式 RAM 用量的測量結果,會將在不同程序間分享的頁面納入考量。任何程序專用的 RAM 頁面都會直接計入 PSS 值,而其他程序共用的網頁則只根據共用量按比例計入 PSS 值。舉例來說,在兩個程序之間共用的網頁,會將其一半大小計入每個程序的 PSS。
PSS 評估的一大優點是,您可以將所有 PSS 相加,藉此查看所有程序使用的實際記憶體。這表示 PSS 是程序的實際 RAM 權重的理想指標,同時可用來與其他程序的 RAM 用量及可用 RAM 總數進行比較。
舉例來說,以下是 Google 地圖在 Nexus 5 裝置上的程序的輸出內容。這裡提供了許多資訊,但以下將列舉討論的重點。
adb shell dumpsys meminfo com.google.android.apps.maps -d
注意:這裡顯示的資訊可能會因平台版本而略有不同,因為部分輸出內容會因平台版本而有所不同。
** MEMINFO in pid 18227 [com.google.android.apps.maps] ** Pss Private Private Swapped Heap Heap Heap Total Dirty Clean Dirty Size Alloc Free ------ ------ ------ ------ ------ ------ ------ Native Heap 10468 10408 0 0 20480 14462 6017 Dalvik Heap 34340 33816 0 0 62436 53883 8553 Dalvik Other 972 972 0 0 Stack 1144 1144 0 0 Gfx dev 35300 35300 0 0 Other dev 5 0 4 0 .so mmap 1943 504 188 0 .apk mmap 598 0 136 0 .ttf mmap 134 0 68 0 .dex mmap 3908 0 3904 0 .oat mmap 1344 0 56 0 .art mmap 2037 1784 28 0 Other mmap 30 4 0 0 EGL mtrack 73072 73072 0 0 GL mtrack 51044 51044 0 0 Unknown 185 184 0 0 TOTAL 216524 208232 4384 0 82916 68345 14570 Dalvik Details .Heap 6568 6568 0 0 .LOS 24771 24404 0 0 .GC 500 500 0 0 .JITCache 428 428 0 0 .Zygote 1093 936 0 0 .NonMoving 1908 1908 0 0 .IndirectRef 44 44 0 0 Objects Views: 90 ViewRootImpl: 1 AppContexts: 4 Activities: 1 Assets: 2 AssetManagers: 2 Local Binders: 21 Proxy Binders: 28 Parcel memory: 18 Parcel count: 74 Death Recipients: 2 OpenSSL Sockets: 2
以下是 Gmail 應用程式 Dalvik 中較舊的 dumpsys:
** MEMINFO in pid 9953 [com.google.android.gm] ** Pss Pss Shared Private Shared Private Heap Heap Heap Total Clean Dirty Dirty Clean Clean Size Alloc Free ------ ------ ------ ------ ------ ------ ------ ------ ------ Native Heap 0 0 0 0 0 0 7800 7637(6) 126 Dalvik Heap 5110(3) 0 4136 4988(3) 0 0 9168 8958(6) 210 Dalvik Other 2850 0 2684 2772 0 0 Stack 36 0 8 36 0 0 Cursor 136 0 0 136 0 0 Ashmem 12 0 28 0 0 0 Other dev 380 0 24 376 0 4 .so mmap 5443(5) 1996 2584 2664(5) 5788 1996(5) .apk mmap 235 32 0 0 1252 32 .ttf mmap 36 12 0 0 88 12 .dex mmap 3019(5) 2148 0 0 8936 2148(5) Other mmap 107 0 8 8 324 68 Unknown 6994(4) 0 252 6992(4) 0 0 TOTAL 24358(1) 4188 9724 17972(2)16388 4260(2)16968 16595 336 Objects Views: 426 ViewRootImpl: 3(8) AppContexts: 6(7) Activities: 2(7) Assets: 2 AssetManagers: 2 Local Binders: 64 Proxy Binders: 34 Death Recipients: 0 OpenSSL Sockets: 1 SQL MEMORY_USED: 1739 PAGECACHE_OVERFLOW: 1164 MALLOC_SIZE: 62
一般來說,請只使用 Pss Total
和 Private Dirty
資料欄。在某些情況下,Private Clean
和 Heap Alloc
資料欄也提供了有趣的資料。您應觀察到的不同記憶體分配 (資料列) 相關資訊:
Dalvik Heap
- 應用程式中 Dalvik 配置使用的 RAM。
Pss Total
會包含所有 Zygote 配置 (如上面的 PSS 定義所述,依據其在不同程序間的共用情況計入權重)。您可以透過Private Dirty
是實際上僅適用於應用程式堆積的 RAM,當中包含您自己的配置,以及自從 Zygote 分出您的應用程式程序以來已修改的任何 Zygote 配置頁面。注意:在含有
Dalvik Other
區段的新版平台上,Dalvik Heap 的Pss Total
和Private Dirty
號碼並不包含 Dalvik 負擔,例如 Just-in 時間編譯 (JIT) 和 GC 記帳,較舊版本則將其組合起來,列在Dalvik
下方。Heap Alloc
是 Dalvik 和原生堆積分配器追蹤的應用程式記憶體量。這個值大於Pss Total
和Private Dirty
,因為您的處理程序是 Zygote 的分支,其中包含了您的程序與所有其他程序共用的配置。 .so mmap
和.dex mmap
- 用於對應
.so
(原生) 和.dex
(Dalvik 或 ART) 程式碼的 RAM。Pss Total
號碼包含各個應用程式共用的平台代碼;Private Clean
是應用程式本身的程式碼。一般來說,實際的對應大小將會大上許多,因為這裡的 RAM 只是 RAM 中目前需要的數量,用於已經由應用程式執行的程式碼。然而,.so mmap 有很大的 Private Dirty,是因為原生程式碼載入至最終地址時已經修正。 .oat mmap
- 這是程式碼映像檔已使用的 RAM 用量,基於多個應用程式常用的預先載入類別。這張圖片會由所有應用程式共用,且不受特定應用程式影響。
.art mmap
- 這個堆積映像檔使用的 RAM 用量取決於許多應用程式常用的預先載入類別。這張圖片會由所有應用程式共用,且不受特定應用程式影響。雖然 ART 映像檔包含
Object
執行個體,但不會計入堆積大小, .Heap
(僅限 -d 旗標)- 這是應用程式的應用程式堆積記憶體大小。不包括映像檔和大型物件空間中的物件,但包含潛在開發空間和非移動空間。
.LOS
(僅限 -d 旗標)- 這是 ART 大型物件空間使用的 RAM 容量。其中包括開發型大型物件。大型物件是所有超過 12 KB 的原始陣列配置。
.GC
(僅限 -d 旗標)- 這是垃圾收集的營運成本。其實沒有任何方法可減少這筆費用。
.JITCache
(僅限 -d 旗標)- 這是 JIT 資料和程式碼快取使用的記憶體量。由於所有的應用程式在安裝時都會編譯,因此通常為 0。
.Zygote
(僅限 -d 旗標)- 這是潛在開發空間的記憶體用量。系統會在裝置啟動時建立複雜空間,因此絕對不會分配。
.NonMoving
(僅限 -d 旗標)- 這是指 ART 非移動空間所使用的 RAM 容量。非移動空間含有特殊的非移動物件,例如欄位和方法。如要減少這個部分,請在應用程式中使用較少欄位和方法。
.IndirectRef
(僅限 -d 旗標)- ART 間接參考表格使用的 RAM 用量。通常這個額度很小,但如果太高,可能會減少本機和全域 JNI 參照的數量,藉此降低費用。
Unknown
- 任何無法歸類到其他特定項目的 RAM 頁面。目前主要包含原生配置,因為位址空間版面配置隨機化 (ASLR) 收集這項資料時,工具無法辨識這些資訊。與 Dalvik 堆積一樣,表示「不明」的
Pss Total
會考慮與 Zygote 共用的情況,而Private Dirty
則表示僅用於您的應用程式的不明 RAM。 TOTAL
- 程序使用的總比例集 (PSS) RAM 總數。這是所有 PSS 欄位的總和。這代表處理程序的整體記憶體權重,可直接與其他程序和可用的 RAM 總量進行比較。
Private Dirty
和Private Clean
是程序中的總分配狀況,不與其他程序共用。一起 (特別是Private Dirty
) 都是您的程序損毀時,要釋出給系統的 RAM 容量。Dirty RAM 是經過修改的網頁,因此必須留在 RAM 環境中 (因為並未發生替換)。Clean RAM 是指對應於永久檔案 (例如執行中的程式碼) 的網頁,如果一段時間內未使用,可能會遭到清除。 ViewRootImpl
- 在程序中正在使用的根資料檢視次數。每個根檢視表都與某個視窗相關聯,因此可協助您識別涉及對話方塊或其他視窗的記憶體流失。
AppContexts
和Activities
- 目前在流程中運作的應用程式
Context
和Activity
物件數量。這可協助您快速識別外洩的Activity
物件,這些物件因存在靜態參照而無法進行垃圾收集,這是很常見的情況。這些物件通常有許多與之關聯的其他配置項目,因此能有效追蹤大量記憶體流失。
注意:View
或 Drawable
物件也會保留對其來源的 Activity
參照,因此保留 View
或 Drawable
物件也可能導致應用程式外洩 Activity
。