測試顯示性能-基于Android M 開發者預覽版

xdld 9年前發布 | 24K 次閱讀 Android M Android開發 移動開發

 

安卓官方文檔的漢化越來越及時了,新出的Android M 開發者預覽版的文檔已經全部翻譯完了 https://developer.android.com/intl/zh-cn/preview/overview.html

這篇文章就是Android M 開發者預覽版專題中的一部分 測試顯示性能 。以下是原文:

用戶界面 (UI) 性能測試可確保您的應用不僅滿足其功能要求,同時確保用戶與應用之間的交互順暢無比,能夠以每秒連續 60 幀( 為什么選擇 60fps? )的幀速運行,而不會出現任何幀丟失或延遲的現象,也就是我們通常所說的“卡頓”。本文檔介紹可用于測量 UI 性能的工具并提出一種將 UI 性能測量集成到測試實踐中的方法。

測量 UI 性能

為了改善性能,您首先必須能夠測量系統性能,然后診斷并識別可能來自管道各個部分的問題。

dumpsys 是一種在設備上運行并轉儲感興趣的系統服務狀態信息的 Android 工具。 通過向 dumpsys 傳遞“gfxinfo”命令,可以提供 logcat 格式的輸出,其中包含有關與錄制階段期間發生的動畫幀相關的性能信息。

> adb shell dumpsys gfxinfo <PACKAGE_NAME>

此命令可以生成多個不同表達形式的幀時間數據。

聚合幀統計信息

借助 M 預覽版,該命令可將在整個進程生命周期中收集的幀數據的聚合分析打印輸出到 logcat。 例如:

Stats since: 752958278148ns
Total frames rendered: 82189
Janky frames: 35335 (42.99%)
90th percentile: 34ms
95th percentile: 42ms
99th percentile: 69ms
Number Missed Vsync: 4706
Number High input latency: 142
Number Slow UI thread: 17270
Number Slow bitmap uploads: 1542
Number Slow draw: 23342

這些高級統計信息可以較高水平地傳達應用的呈現性能及其在多個幀之間的穩定性。

精確的幀時間信息

M 預覽版附帶提供了一個適用于 gfxinfo 的新命令,即:framestats,該命令根據最近的幀提供非常詳細的幀時間信息,讓您能夠更準確地查出并調試問題。

>adb shell dumpsys gfxinfo <PACKAGE_NAME> framestats

此命令根據應用生成的最后 120 幀,打印輸出帶有納秒時間戳的幀時間信息。以下是來自 adb dumpsys gfxinfo <軟件包名稱> framestats 的原始輸出示例:

0,49762224585003,49762241251670,9223372036854775807,0,49762257627204,49762257646058,49762257969704,49762258002100,49762265541631,49762273951162,49762300914808,49762303675954,
0,49762445152142,49762445152142,9223372036854775807,0,49762446678818,49762446705589,49762447268818,49762447388037,49762453551527,49762457134131,49762474889027,49762476150120,
0,49762462118845,49762462118845,9223372036854775807,0,49762462595381,49762462619287,49762462919964,49762462968454,49762476194547,49762476483454,49762480214964,49762480911527,
0,49762479085548,49762479085548,9223372036854775807,0,49762480066370,49762480099339,49762481013089,49762481085850,49762482232152,49762482478350,49762485657620,49762486116683,

每行輸出均代表應用生成的一幀。每行都有固定的列數,用于描述幀生成管道的每個階段所花的時間。 下文將詳細描述此格式,包括每列代表的具體內容。

Framestats 數據格式

由于數據塊是 CSV 格式的輸出,因此將其粘貼到所選的電子表格工具或使用腳本進行收集和解析非常簡單。 下表解釋了輸出數據列的格式。 所有時間戳均以納秒計。

  • 標志

    • 窗口布局發生變化(例如,應用的第一幀或在旋轉后)

    • 此外,如果幀的某些值包含無意義的時間戳,則也可能跳過該幀。 例如,如果幀的運行速度超過 60fps,或者如果屏幕上的所有內容最終都準確無誤,則可能跳過該幀,這不一定表示應用中存在問題。

    • “標志”列帶有“0”的行可以通過從 FRAME_COMPLETED 列中減去 INTENDED_VSYNC 列計算得出總幀時間。

    • 該列為非零值的行將被忽略,因為其對應的幀已被確定為偏離正常性能,其布局和繪制時間預計超過 16 毫秒。 可能出現這種情況有如下幾個原因:

  • INTENDED_VSYNC

    • 幀的預期起點。如果此值不同于 VSYNC,則表示 UI 線程中發生的工作使其無法及時響應垂直同步信號。

  • VSYNC

    • 所有垂直同步偵聽器中使用的時間值和幀繪圖(Choreographer 幀回調、動畫、View.getDrawingTime() 等等)

    • 如需進一步了解 VSYNC 及其對應用產生的影響,請觀看 了解 VSYNC 視頻。

  • OLDEST_INPUT_EVENT

    • 輸入隊列中最早輸入事件的時間戳或 Long.MAX_VALUE(如果幀沒有輸入事件)。

    • 此值主要用于平臺工作,對應用開發者的作用有限。

  • NEWEST_INPUT_EVENT

    • 輸入隊列中最新輸入事件的時間戳或 0(如果幀沒有輸入事件)。

    • 此值主要用于平臺工作,對應用開發者的作用有限。

    • 但是,可以通過查看 (FRAME_COMPLETED - NEWEST_INPUT_EVENT) 大致了解應用增加的延遲時間。

  • HANDLE_INPUT_START

    • 將輸入事件分派給應用的時間戳。

    • 通過觀察此時間戳與 ANIMATION_START 之間的時差,可以測量應用處理輸入事件所花的時間。

    • 如果這個數字較高(> 2 毫秒),則表明應用處理 View.onTouchEvent() 等輸入事件所花的時間太長,這意味著此工作需要進行優化或轉交給其他線程。 請注意,有些情況下(例如,啟動新Activity或類似活動的點擊事件),這個數字較大是預料之中并且可以接受的。

  • ANIMATION_START

    • 在 Choreographer 中注冊的動畫運行的時間戳。

    • 通過觀察此時間戳與 PERFORM_TRANVERSALS_START 之間的時差,可以確定評估正在運行的所有動畫(ObjectAnimator、ViewPropertyAnimator 和通用轉換)所需的時間。

    • 如果這個數字較高(> 2 毫秒),請檢查您的應用是否編寫了任何自定義動畫,或檢查 ObjectAnimator 在對哪些字段設置動畫并確保它們適用于動畫。

    • 如需了解有關 Choreographer 的更多信息,請觀看 利弊 視頻。

  • PERFORM_TRAVERSALS_START

    • 如果您從此值中扣除 DRAW_START,則可推斷出完成布局和測量階段所需的時間(請注意,在滾動或動畫期間,您會希望此時間接近于零)。

    • 如需了解有關呈現管道的測量和布局階段的更多信息,請觀看 失效、布局和性能 視頻。

  • DRAW_START

    • performTraversals 繪制階段的開始時間。這是記錄任何失效視圖的顯示列表的起點。

    • 此時間與 SYNC_START 之間的時差就是對樹中的所有失效視圖調用 View.draw() 所需的時間。

    • 如需了解有關繪圖模型的詳細信息,請參閱 硬件加速失效、布局和性能 視頻。

  • SYNC_START

    • 繪制同步階段的開始時間。

    • 如果此時間與 ISSUE_DRAW_COMMANDS_START 之間的時差較大(約 > 0.4 毫秒),則通常表示繪制了大量必須上傳到 GPU 的新位圖。

    • 如需進一步了解同步階段,請觀看 GPU 呈現模式分析 視頻。

  • ISSUE_DRAW_COMMANDS_START

    • 硬件呈現器開始向 GPU 發出繪圖命令的時間。

    • 此時間與 FRAME_COMPLETED 之間的時差讓您可以大致了解應用生成的 GPU 工作量。 繪制過度或呈現效果不佳等問題都會在此顯示出來。

  • SWAP_BUFFERS

    • 調用 eglSwapBuffers 的時間,此調用不屬于平臺工作,相對乏味。

  • FRAME_COMPLETED

    • 全部完成!處理此幀所花的總時間可以通過執行 FRAME_COMPLETED - INTENDED_VSYNC 計算得出。

您可以通過不同的方法使用此數據。一種簡單卻有用的可視化方式就是在不同的延遲時段中顯示幀時間 (FRAME_COMPLETED - INTENDED_VSYNC) 分布的直方圖(參見下圖)。 此圖直觀地表明,大部分幀非常有效,截止時間遠低于 16 毫秒(顯示為紅色),但是少數幀明顯超出了截止時間。 我們可以觀察此直方圖中的變化趨勢,了解所產生的整體變化或新異常值。 此外,您還可以根據數據中的多個時間戳繪制表示輸入延遲、布局所用時間或其他類似關注指標的圖形。

測試顯示性能-基于Android M 開發者預覽版

簡單的幀時間轉儲

如果在“開發者選項”中將 GPU 呈現模式分析 設置為 在 adb shell dumpsys gfxinfo 中 ,則 adb shell dumpsys gfxinfo命令會打印輸出最近 120 幀的時間信息,這些信息分為幾個不同的類別,其相應的值以制表符分隔。 這些數據可以用于大致表明繪圖管道的哪些部分可能速度較慢。

與上述 framestats 類似,將其粘貼到所選的電子表格工具或使用腳本進行收集和解析同樣非常簡單。 下圖詳細顯示了應用生成的許多幀的具體時間分布。

測試顯示性能-基于Android M 開發者預覽版

運行 gfxinfo、復制輸出、將其粘貼到電子表格應用并將數據繪制成堆積條形圖的結果。

每個垂直條均代表一個動畫幀;其高度代表計算該動畫幀所需的毫秒數。 垂直條的每個彩色分段均代表呈現管道的一個不同階段,因此您可以看到應用的哪些部分可能會出現瓶頸。 如需了解有關呈現管道的詳細信息,請參閱 失效、布局和性能 視頻。

控制統計信息收集的時段

Framestats 和簡單的幀計時均可在極短的時間內(相當于約呈現 2 秒)收集數據。 要精確控制此時間范圍(例如,將數據限制于特定動畫),您可以重置所有計數器并匯總收集的統計信息。

>adb shell dumpsys gfxinfo <PACKAGE_NAME> reset

這也可以與轉儲命令結合使用來定期進行收集和重置,從而持續捕獲時間范圍不到 2 秒的幀。

診斷性能回歸

要查出問題并保持應用運行狀況良好,第一步最好是識別回歸。 但是,dumpsys 僅確定是否存在問題及其相對嚴重性。 您仍需診斷性能問題的具體原因并找到適當的解決方法。 為此,我們強烈建議您使用 systrace 工具。

其他資源

如需了解有關 Android 呈現管道的工作原理、可能存在的常見問題以及如何解決這些問題的詳細信息,以下其他資源可能對您有所幫助:

  • 呈現性能 101

  • 為什么選擇 60fps?

  • Android UI 和 GPU

  • 失效、布局和性能

  • 使用 Systrace 分析 UI 性能

自動化 UI 性能測試

UI 性能測試方法之一是讓測試人員對目標應用執行一系列用戶操作,并目視檢查是否存在卡頓現象,或花費大量時間使用工具驅動型方法來查明是否存在卡頓現象。 但是,這種人工方法充滿風險:人為感知幀率變化的能力參差不齊,并且此過程又費時、繁瑣且易于出錯。

更為有效的方法是記錄并分析自動化 UI 測試中的關鍵性能指標。 Android M 開發者預覽版包括新的日志記錄功能。利用這些功能,您可以輕松確定應用動畫中的卡頓數量和嚴重性,您還可以使用這些功能構建嚴格的流程,用于確定當前性能并跟蹤未來的性能目標。

本文將向您介紹一種使用這些數據自動化性能測試的推薦方法。

此方法主要分為兩個關鍵操作。首先,確定測試對象和測試方法;其次,設置和維護自動化測試環境。

設置 UI 測試

在開始進行自動化測試之前,您必須做出一些較高層次的決策,以便準確了解測試空間和可能存在的需求。

識別要測試的關鍵動畫/流程

請記住,流暢的動畫中斷時,用戶對低劣性能的感觸最深。 因此,在識別要測試的 UI 操作類型時,集中精力處理用戶最常見或對用戶體驗最為重要的關鍵動畫非常有用。 例如,以下是對識別有所幫助的一些常見場景:

  • 滾動主要的 ListView 或 RecyclerView

  • 異步等待周期內的動畫

  • 可能涉及位圖加載/操縱的所有操作

  • 包括 Alpha 值混合處理在內的動畫

  • 使用畫布繪制的自定義視圖

與團隊中的工程師、設計師和產品經理開展合作,優先處理測試覆蓋范圍內的這些關鍵產品動畫。

定義未來的目標并予以跟蹤

從較高層面來看,確定具體的性能目標、專注于編寫測試并收集相關數據至關重要。 例如:

  • 您是否只是首次想要開始跟蹤 UI 性能以了解詳情?

  • 您是否想要防止未來可能引入的性能回歸?

  • 您當前是否有 90% 的幀運行順暢且希望在本季度達到 98%?

  • 您是否有 98% 的幀運行順暢且不希望出現性能回歸?

  • 提高低端設備上的性能是否為您的目標?

在所有這些情況下,您都將需要進行歷史跟蹤,以顯示多個應用版本中的性能。

識別用于測試的設備

應用性能因其所在設備而異。某些設備的內存可能更少,GPU 功能略弱或 CPU 芯片速度較慢。 這意味著動畫在一套硬件上表現良好,但在其他硬件上可能并非如此,而且可能因為其他管道部分中出現的瓶頸表現更為糟糕。 因此,考慮到用戶可能會看到的這種變化,請選取各種設備(包括當前的高端設備、低端設備、平板電腦等)來執行測試。 找出 CPU 性能、RAM、屏幕密度、尺寸等方面的變化。 在高端設備上順利通過的測試在低端設備上可能會失敗。

基本的 UI 測試框架

UI Automator 和  Espresso 等測試套件是為了幫助自動化用戶使用應用過程中的操作而構建。 這些套件是模擬用戶與您的設備進行交互的簡單框架。 要使用這些框架,您需要有效創建通過一組用戶操作運行的獨特腳本,并在設備中演示這些腳本。

通過結合這些自動化測試以及dumpsys gfxinfo,您可以快速創建可再生成的系統,然后您可使用此系統執行測試并測量特定條件的性能信息。

設置自動化 UI 測試

您能夠執行 UI 測試并擁有從單一測試收集數據的管道后,下一個重要步驟就是采用可以在多種設備上多次執行該測試的框架,并匯總生成的性能數據,以供開發團隊做進一步分析。

測試自動化框架

有一點值得注意,UI 測試框架(例如, UI Automator )直接在目標設備/模擬器上運行, 而性能信息收集則是由主機通過 ADB 發送命令來驅動 dumpsys gfxinfo 完成的。 為幫助橋接這些單獨實體的自動化,我們開發了 MonkeyRunner 框架;這是一款在主機上運行的腳本編寫系統,可以向一組連接設備發出命令并從中接收數據。

為正確自動化 UI 性能測試而構建一套腳本時,至少應當能夠利用 monkeyRunner 完成以下任務:

  • 向一個或多個目標設備或模擬器加載并啟動所需的 APK。

  • 啟動 UI Automator 的 UI 測試并允許執行該測試

  • 通過 dumpsys gfxinfo 收集性能信息。

  • 匯總信息并以有效的方式重新向開發者顯示。

分類并解決觀察到的問題

一旦確定問題模式或回歸,下一步就是識別和應用修復。 如果自動化測試框架保持幀的精確時間分解,則可幫助您審查最近的可疑代碼/布局更改(出現回歸時),或在切換到人工調查時縮小分析的系統范圍。 對于人工調查, systrace 是一個很好的著手點,它可顯示有關呈現管道的每個階段、系統中的每個線程和核心以及您定義的任何自定義事件標記的精確時間信息。

準確分析時間

需要注意的是,獲取和測量呈現性能所需的時間并非易事。 就其本質而言,這些數字不具有確定性,往往會隨系統狀態、可用內存量、熱節流以及太陽耀斑到達地面的最后時間而波動。 問題在于,盡管同一測試可以運行兩次,但獲得的結果可能略有不同,它們彼此接近,卻并不完全相同。

以這種方式準確收集和分析數據意味著多次運行同一測試,且以平均值或中值的形式累積結果(為了簡單起見,我們將其稱為“批處理”)。這可為您提供測試性能的粗略近似值,而無需確切的時間。

您可對代碼更改前和更改后的應用均使用批處理,了解這些更改對性能產生的相對影響。 如果更改前批處理的平均幀率大于更改后批處理的平均幀率,則此特定更改通常可為您帶來全面的性能優勢。

這意味著您執行的任何自動化 UI 測試均應考慮這一概念以及測試期間可能出現的任何異常。 例如,如果應用性能因某些設備問題(不是由應用引起)驟降,則您可能需要重新運行批處理以便獲得更精確的時間。

那么,在獲得更有意義的測量結果之前,您應運行多少次測試?至少應運行 10 次,次數越多(例如 50 或 100 次)獲得的結果更精確(當然,您現在是犧牲時間換取精確度)

 本文由用戶 xdld 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!