page.title=表示パフォーマンスのテスト page.image=images/cards/card-test-performance_2x.png page.keywords=パフォーマンス,fps,ツール @jd:body
ユーザー インターフェース(UI)のパフォーマンスをテストすることで、アプリが機能面での要件に合うだけでなく、ユーザーがアプリをスムーズに操作でき、毎秒安定して 60 フレーム(why 60fps?)で、フレームのドロップや遅延なしで、言い換えればジャンクなしで実行されるようにします。 このドキュメントでは、UI のパフォーマンスを測定することができるツールについて説明し、UI パフォーマンスの測定値をテストで活用する方法を提示します。
パフォーマンスを改善するには、まずシステムのパフォーマンスを測定し、次にパイプラインのさまざまな箇所で発生している問題を診断し識別する必要があります。
dumpsys は端末上で動作し、システム サービスの状態についての情報をダンプする Android ツールです。 gfxinfo コマンドを dumpsys に渡すと、記録中に実行されたアニメーションのフレームに関連するパフォーマンス情報が logcat に出力されます。
> adb shell dumpsys gfxinfo <PACKAGE_NAME>
このコマンドは、フレーム タイミング データの複数の異なるバリアントを生成することがあります。
M Preview では、このコマンドは、プロセスの生存期間全体を通して収集したフレームのデータの集計結果を 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 Preview では、gfxinfo のための新しいコマンド、framestats が採用され、最新のフレームのフレーム タイミングのきわめて詳細な情報を提供します。そのため、より正確に問題を追跡しデバッグできるようになります。
>adb shell dumpsys gfxinfo <PACKAGE_NAME> framestats
このコマンドは、アプリによって生成された最新 120 フレームのフレーム タイミング情報を、ナノ秒の精度を持つタイムスタンプを使用して出力します。以下は、adb dumpsys gfxinfo <PACKAGE_NAME> 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,
この出力の各行が、アプリによって生成される 1 つのフレームを示します。各ラインは、フレームを生成するパイプラインの各段階で費やされた時間を出力する固定された数の列を持ちます。 次のセクションでは、各列が何を示しているかも含めて、フォーマットを詳細に説明します。
データは CSV 形式で出力されるため、お好みのスプレッドシート ツールに簡単に貼り付けたり、スクリプトで簡単に集計して解析したりできます。 以下のリストは、出力データ列のフォーマットを説明しています。 すべてのタイムスタンプはナノ秒単位で出力されます。
このデータは、別の方法でも使用できます。たとえば、さまざまな遅延バケットでのフレームの処理にかかった時間(FRAME_COMPLETED - INTENDED_VSYNC)の分布を示す下記のヒストグラムは、単純ですが役に立ちます。 このグラフを一目見るだけで、大部分のフレームは 16 ミリ秒の限界線(赤色の線)を大きく下回った良好な状態であるけれども、いくつかのフレームが限界線を著しく上回っていることがわかります。 ヒストグラムで時間の経過に伴う変化を確認することで、大規模な変化が起きているのか、新しい外れ値が作成されているのか知ることができます。 また、データに含まれる多くのタイムスタンプに基づいて、入力待ち時間、レイアウトにかかった時間、その他のこれに類する興味を引く指標をグラフにできます。
[開発者向けオプション] で [GPUレンダリングのプロフィール作成] を [adb shell dumpsys gfxinfo] に設定すると、adb shell dumpsys gfxinfo
コマンドにより、最新の 120 フレームのタイミング情報が、いくつかの異なるカテゴリに分かれて、タブ区切りで出力されます。
このデータは、描画パイプラインのどの部分の処理が遅いのかを大まかに知るのに役に立ちます。
上記の framestats と同様に、お好みのスプレッドシート ツールに簡単に貼り付けたり、スクリプトで簡単に集計し解析したりできます。 以下のグラフは、アプリによって生成された多くのフレームが時間を費やした箇所の内訳を示しています。
このグラフは、gfxinfo を実行し、出力結果をコピーし、スプレッドシート アプリケーションに貼り付け、データを積み上げ棒グラフにしたものです。
各縦棒は、アニメーションの 1 フレームを示し、その高さはそのフレームを処理するのにかかるミリ秒の数を示しています。 また、縦棒の色分けされた各部分は、レンダリング パイプラインの各段階を示しています。これにより、ボトルネックを生んでいる可能性があるのはアプリケーションのどの箇所か確認できます。 レンダリング パイプラインとその最適化方法に関する詳細は、Invalidations, Layouts and Performance のビデオをご覧ください。
Framestats と簡易フレーム タイミングの両方とも、非常に短いウィンドウを通じて、約 2 秒相当のレンダリングについてデータを収集しています。 たとえば、収集するデータを特定のアニメーションだけに限定したい場合、このタイミング データ収集用ウィンドウを正確にコントロールするには、すべてのカウンタをリセットし収集したデータを集計します。
>adb shell dumpsys gfxinfo <PACKAGE_NAME> reset
これは、ダンプ コマンドとあわせて使用することもでき、フレームの 2 秒未満のウィンドウを続けてキャプチャしながら、通常の流れで収集しリセットできます。
パフォーマンスの低下を見つけることは、問題を見つけだし、アプリケーションの状態を良好に維持するための最初のステップです。 ただし、dumpsys は、ただ問題の存在とその相対的な深刻度を明らかにするだけです。 さらに、パフォーマンスの問題の具体的な原因を突き止め、解決するための適切な方法を見つける必要があります。 それには、systrace ツールを利用することをお勧めします。
Android のレンダリング パイプラインの仕組み、一般的な問題、それらの問題の修正方法についての詳細は、以下の資料が役に立ちます。
UI パフォーマンスのテスト手法の 1 つに、対象のアプリ上で一連のユーザー操作を人間のテスターに実行してもらい、目視でジャンクを探すかツール主体の手法を使用して長い時間を費やしてジャンクを見つけるかのいずれかの方法をとるというものがあります。 ただし、この人の力による方法は危険を伴います。フレームレートの変化に気付く能力は、人によって大きく異なります。また、この方法は、多くの時間が必要で単調で退屈なものであり、ミスも起こりがちです。
より効率的な手法は、自動化された UI テストにより主要なパフォーマンス指標のログを取って解析することです。 Android M Developer Preview には、アプリケーションのアニメーションに対するジャンクの量と深刻度を簡単に確認することができ、現在のパフォーマンスを確認し将来のパフォーマンス目標を実現するための適切なプロセスを構築するために使用できる新しいログ記録機能が含まれています。
このドキュメントでは、この新しいログ機能によるデータを使用してパフォーマンス テストを自動化するための手法について紹介します。
この手法には、鍵となるアクションが 2 つあります。何をどのようにテストするかということを明確にすることと、自動化されたテスト環境をセットアップし管理することです。
自動化されたテストを実行する前に、テストの仕様や必要になる可能性があるものを適切に把握するために、いくつかの大まかな決定をしておくことが重要です。
パフォーマンスの低さがユーザーの目に最も多く触れるのは、アニメーションのスムーズさが失われる場合です。 そのため、どのタイプの UI アクションをテストするか決めるときに、ユーザーが最もよく見る重要なアニメーションまたはユーザーの使用感にとって最も重要なアニメーションにフォーカスすると効果があります。 以下にいくつかの一般的なシナリオをご紹介します。
チームのエンジニア、デザイナー、プロダクト マネージャーと連携して、テスト範囲のこれらの重要な製品アニメーションの優先順位を決めてください。
具体的なパフォーマンス目標を明確にし、その目標に合わせてテストを作成しデータを収集することが重要な場合もあります。 次に例を示します。
上記のすべての場合で、複数のバージョンのアプリケーションでのパフォーマンスを示すヒストリカル トラッキングが必要です。
アプリケーションのパフォーマンスは、そのアプリケーションが実行される端末によって異なります。端末によっては、メモリが少なく、GPU のパワーが低く、CPU チップが遅いものもあります。 つまり、あるハードウェアでスムーズに実行できるアニメーションが別のハードウェアではうまく実行できなかったり、さらに悪い場合は、パイプラインの別の箇所にボトルネックを生んだりすることになります。 そのため、このようなハードウェアの違いに対処するために、最新のハイエンド端末と、ローエンド端末、タブレットなどの幅広い端末を選んでテストを実行する必要があります。 さまざまな CPU 性能、RAM、画面密度、サイズ等の端末を用意してください。 ハイエンド端末でうまくいったテストが、ローエンド端末では失敗することがあります。
UI Automator や Espresso といったツールが、ユーザーがアプリケーション内を移動する動作を自動処理にするために用意されています。 これらは、端末でのユーザーの操作を模倣するシンプルなフレームワークです。 これらのフレームワークを使用するには、一連のユーザー アクションを実行する独自のスクリプトを作成して、端末上で実行します。
dumpsys gfxinfo
と、これらの自動化されたテストを組み合わせることで、テストを実行できる再現可能なシステムを簡単に作成して、特定の条件でのパフォーマンス情報を測定できます。
UI テストを実行する機能と、1 つのテストからデータを集めるためのパイプラインを用意したら、次の重要なステップは、複数の端末で、そのテストを複数回実行でき、開発チームの解析用にパフォーマンス データを集計できるフレームワークを用意することです。
UI テストのフレームワーク(UI Automator など)は、対象の端末やエミュレータ上で直接実行されます。 dumpsys gfxinfo によるパフォーマンス情報の収集はホストマシンによって行われますが、コマンドの送信は ADB を通じて行われます。 これらの別々に分かれている処理の自動化を橋渡しするために、MonkeyRunner フレームワークは開発されました。このフレームワークは、ホストマシンで動作するスクリプティング システムで、接続されている端末にコマンドを発行できるとともに、それらの端末からデータを受け取ることもできます。
UI パフォーマンス テストの適切な自動化のためのスクリプトを作成することで、少なくとも、以下のタスクを MonkeyRunner を利用して実行することが可能になります。
問題のパターンまたはパフォーマンスの低下を確認したら、次に必要なことは問題の解決方法を見つけその方法を実行することです。 その自動化されたテスト フレームワークがフレームの正確なタイミングの内訳を保存している場合、最近行われたコードやレイアウトの疑わしい変更を調べたり(パフォーマンスが低下している場合)、手作業での調査に切り替えたときにシステムのどの箇所を解析するか絞り込んだりするのに役立ちます。 手作業での調査は、まず systrace から開始することをお勧めします。systrace は、システムのレンダリング パイプラインのすべての段階、すべてのスレッド、コア、およびテスト担当者が定義したカスタム イベントについての正確なタイミング情報を表示します。
レンダリング パフォーマンスのタイミングを取得し測定することには困難を伴います。 これらの数値は、その本質として、決定的なものではなく、多くの場合、システムの状態、利用可能なメモリ量、サーマル・スロットリング、その地域に最後に日照があった時間などに応じて変動します。 つまり同じテストを 2 度実行した場合、近似するが完全に同じではない、わずかに異なる結果が出ることがあるということです。
この方法で適切にデータを集めプロファイリングするには、同じテストを複数回実行し、結果を平均値または中間値として集計します(以下では、この処理を「バッチ」と記載します)。これにより、テストのパフォーマンスの大まかな数字を、正確なタイミングを必要とすることなく取得できます。
バッチは、コード変更の合間にも、それらの変更がパフォーマンスにもたらす相対的な影響を確認するために使用できます。 変更前のバッチの平均フレームレートが変更後のバッチよりも大きい場合、通常、WRT パフォーマンスが全面的に改善したと言えます。
つまり、自動化された UI テストでは、この考え方を取り入れることと、テスト中に発生する可能性のある異常を把握しておくことが必要です。 たとえば、アプリケーションのパフォーマンスが、そのアプリケーションではなく何らかの端末の問題により突然低下した場合、通常時のタイミングを取得するためにバッチを再度実行した方がよいことがあります。
それでは、測定値を意味のあるものにするには、何回テストを実行すればよいでしょうか。少なくとも 10 回は必要であり、50 回や 100 回などのように回数が多いほど正確な結果が得られます(もちろん、時間と正確さはトレードオフの関係にあります)。