summaryrefslogtreecommitdiffstats
path: root/docs/html-intl/intl/ja/preview/testing/performance.jd
blob: 1c3ae02290f1c48b3d0a8815a3874b3bfdc4a72e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
page.title=表示パフォーマンスのテスト
page.image=images/cards/card-test-performance_2x.png
page.keywords=パフォーマンス,fps,ツール

@jd:body


<div id="qv-wrapper">
  <div id="qv">
    <h2>本書の内容</h2>
      <ol>
        <li><a href="#measure">UI のパフォーマンスを測定する</a>
          <ul>
            <li><a href="#aggregate">フレームのデータを集計する</a></li>
            <li><a href="#timing-info">正確なフレーム タイミング情報</a></li>
            <li><a href="#timing-dump">簡易フレーム タイミング ダンプ</a></li>
            <li><a href="#collection-window">データ収集用のウィンドウを制御する</a></li>
            <li><a href="#diagnose">パフォーマンスの低下を診断する</a></li>
            <li><a href="#resources">追加リソース</a></li>
          </ul>
        </li>
        <li><a href="#automate">UI パフォーマンス テストを自動化する</a>
          <ul>
            <li><a href="#ui-tests">UI テストをセットアップする</a></li>
            <li><a href="#automated-tests">自動化された UI テストをセットアップする</a></li>
            <li><a href="#triage">見つけた問題を選別し解決する</a></li>
          </ul>
        </li>
      </ol>
  </div>
</div>


<p>
  ユーザー インターフェース(UI)のパフォーマンスをテストすることで、アプリが機能面での要件に合うだけでなく、ユーザーがアプリをスムーズに操作でき、毎秒安定して 60 フレーム(<a href="https://www.youtube.com/watch?v=CaMTIgxCSqU&amp;index=25&amp;list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">why 60fps?</a>)で、フレームのドロップや遅延なしで、言い換えれば<em>ジャンク</em>なしで実行されるようにします。


このドキュメントでは、UI のパフォーマンスを測定することができるツールについて説明し、UI パフォーマンスの測定値をテストで活用する方法を提示します。


</p>


<h2 id="measure">UI のパフォーマンスを測定する</h2>

<p>
  パフォーマンスを改善するには、まずシステムのパフォーマンスを測定し、次にパイプラインのさまざまな箇所で発生している問題を診断し識別する必要があります。


</p>

<p>
  <em><a href="https://source.android.com/devices/tech/debug/dumpsys.html">dumpsys</a></em> は端末上で動作し、システム サービスの状態についての情報をダンプする Android ツールです。

<em>gfxinfo</em> コマンドを dumpsys に渡すと、記録中に実行されたアニメーションのフレームに関連するパフォーマンス情報が logcat に出力されます。


</p>

<pre>
&gt; adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt;
</pre>

<p>
  このコマンドは、フレーム タイミング データの複数の異なるバリアントを生成することがあります。
</p>

<h3 id="aggregate">フレームのデータを集計する</h3>

<p>
  M Preview では、このコマンドは、プロセスの生存期間全体を通して収集したフレームのデータの集計結果を logcat に出力します。
次に例を示します。
</p>

<pre class="noprettyprint">
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
</pre>

<p>
  これらのデータは、アプリのレンダリングのパフォーマンスと多くのフレームの全体での安定性を大まかに示します。

</p>


<h3 id="timing-info">正確なフレーム タイミング情報</h3>

<p>
  M Preview では、gfxinfo のための新しいコマンド、<em>framestats</em> が採用され、最新のフレームのフレーム タイミングのきわめて詳細な情報を提供します。そのため、より正確に問題を追跡しデバッグできるようになります。


</p>

<pre>
&gt;adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt; framestats
</pre>

<p>
  このコマンドは、アプリによって生成された最新 120 フレームのフレーム タイミング情報を、ナノ秒の精度を持つタイムスタンプを使用して出力します。以下は、adb dumpsys gfxinfo
  &lt;PACKAGE_NAME&gt; framestats による未加工の出力例です。

</p>

<pre class="noprettyprint">
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,
</pre>

<p>
  この出力の各行が、アプリによって生成される 1 つのフレームを示します。各ラインは、フレームを生成するパイプラインの各段階で費やされた時間を出力する固定された数の列を持ちます。
次のセクションでは、各列が何を示しているかも含めて、フォーマットを詳細に説明します。

</p>


<h4 id="fs-data-format">Framestats データ形式</h4>

<p>
  データは CSV 形式で出力されるため、お好みのスプレッドシート ツールに簡単に貼り付けたり、スクリプトで簡単に集計して解析したりできます。
以下のリストは、出力データ列のフォーマットを説明しています。
すべてのタイムスタンプはナノ秒単位で出力されます。
</p>

<ul>
  <li>FLAGS
    <ul>
      <li>FLAGS 列が「0」の行には、FRAME_COMPLETED 列から INTENDED_VSYNC 列を引いて計算されたフレームの総処理時間が示されます。

      </li>

      <li>FLAGS 列が「0」以外の場合、そのフレームは通常のパフォーマンスからの外れ値であると定められているのでその行は無視する必要があります。この場合、レイアウトと描画に 16 ミリ秒よりも長くかかることが想定されています。

これは、以下の原因で起きることがあります。
        <ul>
          <li>ウィンドウのレイアウトが変更された(アプリケーションの最初のフレームの場合や画面が回転された後など)。

          </li>

          <li>フレームが省略された。この場合、いくつかの値には不適切なタイムスタンプが含まれます。
たとえば 60 fps よりも速く実行されている場合や、画面上にダーティで終わったものが何もない場合など、フレームは省略することができます。これは必ずしもアプリに問題がある兆候ではありません。


          </li>
        </ul>
      </li>
    </ul>
  </li>

  <li>INTENDED_VSYNC
    <ul>
      <li>フレームの意図された開始ポイント。この値が VSYNC と異なる場合、vsync 信号にすぐに応答することを阻止する動作が UI スレッド上で発生していたことを意味します。


      </li>
    </ul>
  </li>

  <li>VSYNC
    <ul>
      <li>すべての vsync リスナーとフレームの描画(Choreographer フレーム コールバック、アニメーション、View.getDrawingTime() など)で使用された時間の値。

      </li>

      <li>VSYNC と VSYNC のアプリケーションへの影響の詳細については、<a href="https://www.youtube.com/watch?v=1iaHxmfZGGc&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=23">Understanding VSYNC</a> のビデオをご覧ください。


      </li>
    </ul>
  </li>

  <li>OLDEST_INPUT_EVENT
    <ul>
      <li>入力キューの最も古い入力イベントのタイムスタンプ。フレームの入力イベントが存在しない場合は、Long.MAX_VALUE。

      </li>

      <li>この値は、主にプラットフォームの動作のパフォーマンスを示すことを意図しており、アプリのデベロッパーが活用できる場面は限定されます。

      </li>
    </ul>
  </li>

  <li>NEWEST_INPUT_EVENT
    <ul>
      <li>入力キューの最も新しい入力イベントのタイムスタンプ。フレームの入力イベントが存在しない場合は、0。

      </li>

      <li>この値は、主にプラットフォームの動作のパフォーマンスを示すことを意図しており、アプリのデベロッパーが活用できる場面は限定されます。

      </li>

      <li>ただし、FRAME_COMPLETED から NEWEST_INPUT_EVENT を引いた値を確認することによって、そのアプリが増やす待ち時間がどれくらいか大まかに知ることができます。

      </li>
    </ul>
  </li>

  <li>HANDLE_INPUT_START
    <ul>
      <li>入力イベントがアプリケーションにディスパッチされるときのタイムスタンプ。
      </li>

      <li>この値と ANIMATION_START との間の時間を確認することで、アプリケーションが入力イベントを処理するために費やした時間を測定することができます。

      </li>

      <li>この値が大きい(&gt; 2 ミリ秒)の場合、View.onTouchEvent() などの入力イベントを処理するためにアプリが長い時間を費やしていることを意味します。これは、この動作の最適化または別のスレッドへの移行が必要なことを示している場合があります。

新しいアクティビティやそれに類するものを起動するクリック イベントなどの一部のシナリオでは、この値が大きいことは想定済みであり許容範囲内です。


      </li>
    </ul>
  </li>

  <li>ANIMATION_START
    <ul>
      <li>Choreographer を使用して登録されたアニメーションが実行されたときのタイムスタンプ。
      </li>

      <li>この値と PERFORM_TRANVERSALS_START の間の時間を確認することで、実行中のすべてのアニメーター(ObjectAnimator、ViewPropertyAnimator、共通の遷移となっている Transitions)を評価するのにかかった時間を確認することができます。


      </li>

      <li>この値が大きい(&gt; 2 ミリ秒)の場合、アプリがカスタム アニメーターを記述していないか、また ObjectAnimators がアニメーション化しているのがどの項目かを確認して、それらがアニメーションに適しているかどうか確かめてください。


      </li>

      <li>Choreographer についての詳細は、<a href="https://developers.google.com/events/io/sessions/325418001">For Butter or Worse</a> のビデオをご覧ください。

      </li>
    </ul>
  </li>

  <li>PERFORM_TRAVERSALS_START
    <ul>
      <li>この値から DRAW_START を引くと、レイアウトと測定のフェーズが完了するまでにかかる時間を知ることができます(スクロールまたはアニメーションの間は、この時間がゼロに近いことが望ましいことにご注意ください)。


      </li>

      <li>レンダリング パイプラインのレイアウトと測定のフェーズについての詳細は、<a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=27">Invalidations, Layouts and Performance</a> のビデオをご覧ください。


      </li>
    </ul>
  </li>

  <li>DRAW_START
    <ul>
      <li>performTraversals の描画のフェーズが開始された時間。これは、無効化されているビューのディスプレイ リストを記録する開始ポイントです。

      </li>

      <li>この値と SYNC_START の間の時間は、ツリー内のすべての無効化されているビュー上で View.draw() を呼び出すのにかかった時間を示します。

      </li>

      <li>描画モデルに関する詳細は、<a href="{@docRoot}guide/topics/graphics/hardware-accel.html#hardware-model">Hardware Acceleration</a> または <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=27">Invalidations, Layouts and Performance</a> のビデオをご覧ください。


      </li>
    </ul>
  </li>

  <li>SYNC_START
    <ul>
      <li>描画の同期フェーズが開始された時間。
      </li>

      <li>この値と ISSUE_DRAW_COMMANDS_START の間の時間が非常に大きい場合(&gt; 0.4 ミリ秒またはこれに近い値)、通常は、GPU にアップロードする必要がある多くの新しい Bitmaps が描画されたこと意味します。


      </li>

      <li>同期フェーズについての詳細は、<a href="https://www.youtube.com/watch?v=VzYkVL1n4M8&amp;index=24&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu">Profile GPU Rendering</a> のビデオをご覧ください。

      </li>
    </ul>
  </li>

  <li>ISSUE_DRAW_COMMANDS_START
    <ul>
      <li>ハードウェア レンダラーが、GPU への描画コマンドの発行を開始した時間。
      </li>

      <li>この値と FRAME_COMPLETED の間の時間により、そのアプリがどれくらいの量の GPU 作業を生じさせているのか大まかに知ることができます。
オーバードローが多すぎたりまたはレンダリング効果が不十分だったりという問題がある場合は、この時間にあらわれます。

      </li>
    </ul>
  </li>

  <li>SWAP_BUFFERS
    <ul>
      <li>eglSwapBuffers が呼び出された時間。プラットフォーム作業関連以外では、あまり重要ではない値です。

      </li>
    </ul>
  </li>

  <li>FRAME_COMPLETED
    <ul>
      <li>すべてが完了した時間です。そのフレームを処理するのにかかった時間の合計は、FRAME_COMPLETED から INTENDED_VSYNC を引くと計算できます。

      </li>
    </ul>
  </li>

</ul>

<p>
  このデータは、別の方法でも使用できます。たとえば、さまざまな遅延バケットでのフレームの処理にかかった時間(FRAME_COMPLETED - INTENDED_VSYNC)の分布を示す下記のヒストグラムは、単純ですが役に立ちます。

このグラフを一目見るだけで、大部分のフレームは 16 ミリ秒の限界線(赤色の線)を大きく下回った良好な状態であるけれども、いくつかのフレームが限界線を著しく上回っていることがわかります。

ヒストグラムで時間の経過に伴う変化を確認することで、大規模な変化が起きているのか、新しい外れ値が作成されているのか知ることができます。
また、データに含まれる多くのタイムスタンプに基づいて、入力待ち時間、レイアウトにかかった時間、その他のこれに類する興味を引く指標をグラフにできます。


</p>

<img src="{@docRoot}preview/images/perf-test-framestats.png">


<h3 id="timing-dump">簡易フレーム タイミング ダンプ</h3>

<p>
  [開発者向けオプション] で [<strong>GPUレンダリングのプロフィール作成</strong>] を [<strong>adb shell dumpsys gfxinfo</strong>] に設定すると、<code>adb shell dumpsys gfxinfo</code> コマンドにより、最新の 120 フレームのタイミング情報が、いくつかの異なるカテゴリに分かれて、タブ区切りで出力されます。


このデータは、描画パイプラインのどの部分の処理が遅いのかを大まかに知るのに役に立ちます。

</p>

<p>
  上記の <a href="#fs-data-format">framestats</a> と同様に、お好みのスプレッドシート ツールに簡単に貼り付けたり、スクリプトで簡単に集計し解析したりできます。

以下のグラフは、アプリによって生成された多くのフレームが時間を費やした箇所の内訳を示しています。

</p>

<img src="{@docRoot}preview/images/perf-test-frame-latency.png">

<p>
  このグラフは、gfxinfo を実行し、出力結果をコピーし、スプレッドシート アプリケーションに貼り付け、データを積み上げ棒グラフにしたものです。

</p>

<p>
  各縦棒は、アニメーションの 1 フレームを示し、その高さはそのフレームを処理するのにかかるミリ秒の数を示しています。
また、縦棒の色分けされた各部分は、レンダリング パイプラインの各段階を示しています。これにより、ボトルネックを生んでいる可能性があるのはアプリケーションのどの箇所か確認できます。

レンダリング パイプラインとその最適化方法に関する詳細は、<a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;index=27&amp;list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">Invalidations, Layouts and Performance</a> のビデオをご覧ください。


</p>


<h3 id="collection-window">データ収集用のウィンドウを制御する</h3>

<p>
  Framestats と簡易フレーム タイミングの両方とも、非常に短いウィンドウを通じて、約 2 秒相当のレンダリングについてデータを収集しています。
たとえば、収集するデータを特定のアニメーションだけに限定したい場合、このタイミング データ収集用ウィンドウを正確にコントロールするには、すべてのカウンタをリセットし収集したデータを集計します。


</p>

<pre>
&gt;adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt; reset
</pre>

<p>
  これは、ダンプ コマンドとあわせて使用することもでき、フレームの 2 秒未満のウィンドウを続けてキャプチャしながら、通常の流れで収集しリセットできます。


</p>


<h3 id="diagnose">パフォーマンスの低下を診断する</h3>

<p>
  パフォーマンスの低下を見つけることは、問題を見つけだし、アプリケーションの状態を良好に維持するための最初のステップです。
ただし、dumpsys は、ただ問題の存在とその相対的な深刻度を明らかにするだけです。
さらに、パフォーマンスの問題の具体的な原因を突き止め、解決するための適切な方法を見つける必要があります。
それには、<a href="{@docRoot}tools/help/systrace.html">systrace</a> ツールを利用することをお勧めします。

</p>


<h3 id="resources">追加リソース</h3>

<p>
  Android のレンダリング パイプラインの仕組み、一般的な問題、それらの問題の修正方法についての詳細は、以下の資料が役に立ちます。


</p>

<ul>
  <li>Rendering Performance 101
  </li>
  <li>Why 60fps?
  </li>
  <li>Android UI and the GPU
  </li>
  <li>Invalidations Layouts and performance
  </li>
  <li>Analyzing UI Performance with Systrace
  </li>
</ul>


<h2 id="automate">UI パフォーマンス テストを自動化する</h2>

<p>
  UI パフォーマンスのテスト手法の 1 つに、対象のアプリ上で一連のユーザー操作を人間のテスターに実行してもらい、目視でジャンクを探すかツール主体の手法を使用して長い時間を費やしてジャンクを見つけるかのいずれかの方法をとるというものがあります。

ただし、この人の力による方法は危険を伴います。フレームレートの変化に気付く能力は、人によって大きく異なります。また、この方法は、多くの時間が必要で単調で退屈なものであり、ミスも起こりがちです。


</p>

<p>
  より効率的な手法は、自動化された UI テストにより主要なパフォーマンス指標のログを取って解析することです。
Android M Developer Preview には、アプリケーションのアニメーションに対するジャンクの量と深刻度を簡単に確認することができ、現在のパフォーマンスを確認し将来のパフォーマンス目標を実現するための適切なプロセスを構築するために使用できる新しいログ記録機能が含まれています。



</p>

<p>
  このドキュメントでは、この新しいログ機能によるデータを使用してパフォーマンス テストを自動化するための手法について紹介します。

</p>

<p>
  この手法には、鍵となるアクションが 2 つあります。何をどのようにテストするかということを明確にすることと、自動化されたテスト環境をセットアップし管理することです。


</p>


<h3 id="ui-tests">UI テストをセットアップする</h3>

<p>
  自動化されたテストを実行する前に、テストの仕様や必要になる可能性があるものを適切に把握するために、いくつかの大まかな決定をしておくことが重要です。

</p>

<h4>
  テストする重要なアニメーションやフローを明確にする
</h4>

<p>
  パフォーマンスの低さがユーザーの目に最も多く触れるのは、アニメーションのスムーズさが失われる場合です。
そのため、どのタイプの UI アクションをテストするか決めるときに、ユーザーが最もよく見る重要なアニメーションまたはユーザーの使用感にとって最も重要なアニメーションにフォーカスすると効果があります。

以下にいくつかの一般的なシナリオをご紹介します。
</p>

<ul>
  <li>プライマリ ListView または RecyclerView のスクロール
  </li>

  <li>非同期処理待ちサイクル中のアニメーション
  </li>

  <li>ビットマップを読み込んだり操作したりするアニメーション
  </li>

  <li>アルファブレンドを含むアニメーション
  </li>

  <li>キャンバスを使用して描画するカスタムビュー
  </li>
</ul>

<p>
  チームのエンジニア、デザイナー、プロダクト マネージャーと連携して、テスト範囲のこれらの重要な製品アニメーションの優先順位を決めてください。

</p>

<h4>
  将来の目標を決め、実現を目指す
</h4>

<p>
  具体的なパフォーマンス目標を明確にし、その目標に合わせてテストを作成しデータを収集することが重要な場合もあります。
次に例を示します。
</p>

<ul>
  <li>詳細を知るために、初めて UI パフォーマンスの追跡を開始したいだけですか。
  </li>

  <li>将来発生する可能性のあるパフォーマンスの低下を防止したいですか。
  </li>

  <li>現在のフレームのスムーズ度合いは 90% で、今四半期中に 98 % にしたいと考えていますか。
  </li>

  <li>現在のフレームのスムーズ度合い 98% を低下させたくないと考えていますか。
  </li>

  <li>ローエンド端末でのパフォーマンスを改善することが目標ですか。
  </li>
</ul>

<p>
  上記のすべての場合で、複数のバージョンのアプリケーションでのパフォーマンスを示すヒストリカル トラッキングが必要です。

</p>

<h4>
  テストする端末を明確にする
</h4>

<p>
  アプリケーションのパフォーマンスは、そのアプリケーションが実行される端末によって異なります。端末によっては、メモリが少なく、GPU のパワーが低く、CPU チップが遅いものもあります。
つまり、あるハードウェアでスムーズに実行できるアニメーションが別のハードウェアではうまく実行できなかったり、さらに悪い場合は、パイプラインの別の箇所にボトルネックを生んだりすることになります。

そのため、このようなハードウェアの違いに対処するために、最新のハイエンド端末と、ローエンド端末、タブレットなどの幅広い端末を選んでテストを実行する必要があります。

さまざまな CPU 性能、RAM、画面密度、サイズ等の端末を用意してください。
ハイエンド端末でうまくいったテストが、ローエンド端末では失敗することがあります。

</p>

<h4>
  UI のテストの基本的なフレームワーク
</h4>

<p>
  <a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a> や <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso</a> といったツールが、ユーザーがアプリケーション内を移動する動作を自動処理にするために用意されています。

これらは、端末でのユーザーの操作を模倣するシンプルなフレームワークです。
これらのフレームワークを使用するには、一連のユーザー アクションを実行する独自のスクリプトを作成して、端末上で実行します。


</p>

<p>
  <code>dumpsys gfxinfo</code> と、これらの自動化されたテストを組み合わせることで、テストを実行できる再現可能なシステムを簡単に作成して、特定の条件でのパフォーマンス情報を測定できます。


</p>


<h3 id="automated-tests">自動化された UI テストをセットアップする</h3>

<p>
  UI テストを実行する機能と、1 つのテストからデータを集めるためのパイプラインを用意したら、次の重要なステップは、複数の端末で、そのテストを複数回実行でき、開発チームの解析用にパフォーマンス データを集計できるフレームワークを用意することです。



</p>

<h4>
  テスト自動化のためのフレームワーク
</h4>

<p>
  UI テストのフレームワーク(<a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a> など)は、対象の端末やエミュレータ上で直接実行されます。
<em>dumpsys gfxinfo</em> によるパフォーマンス情報の収集はホストマシンによって行われますが、コマンドの送信は ADB を通じて行われます。
これらの別々に分かれている処理の自動化を橋渡しするために、<a href="{@docRoot}tools/help/monkeyrunner_concepts.html">MonkeyRunner</a> フレームワークは開発されました。このフレームワークは、ホストマシンで動作するスクリプティング システムで、接続されている端末にコマンドを発行できるとともに、それらの端末からデータを受け取ることもできます。



</p>

<p>
  UI パフォーマンス テストの適切な自動化のためのスクリプトを作成することで、少なくとも、以下のタスクを MonkeyRunner を利用して実行することが可能になります。

</p>

<ul>
  <li>対象の端末(1 台または複数台)またはエミュレータに任意の APK をロードして起動する
  </li>

  <li>UI Automator UI テストを起動して、実行できるようにする
  </li>

  <li><em>dumpsys gfxinfo</em>を通じて情報を収集する。<em></em>
  </li>

  <li>情報を集計し、デベロッパーに役に立つ形で表示する。
  </li>
</ul>


<h3 id="triage">見つけた問題を選別し解決する</h3>

<p>
  問題のパターンまたはパフォーマンスの低下を確認したら、次に必要なことは問題の解決方法を見つけその方法を実行することです。
その自動化されたテスト フレームワークがフレームの正確なタイミングの内訳を保存している場合、最近行われたコードやレイアウトの疑わしい変更を調べたり(パフォーマンスが低下している場合)、手作業での調査に切り替えたときにシステムのどの箇所を解析するか絞り込んだりするのに役立ちます。


手作業での調査は、まず <a href="{@docRoot}tools/help/systrace.html">systrace</a> から開始することをお勧めします。systrace は、システムのレンダリング パイプラインのすべての段階、すべてのスレッド、コア、およびテスト担当者が定義したカスタム イベントについての正確なタイミング情報を表示します。


</p>

<h4>
  一時的なタイミングを適切にプロファイリングする
</h4>

<p>
  レンダリング パフォーマンスのタイミングを取得し測定することには困難を伴います。
これらの数値は、その本質として、決定的なものではなく、多くの場合、システムの状態、利用可能なメモリ量、サーマル・スロットリング、その地域に最後に日照があった時間などに応じて変動します。

つまり同じテストを 2 度実行した場合、近似するが完全に同じではない、わずかに異なる結果が出ることがあるということです。


</p>

<p>
  この方法で適切にデータを集めプロファイリングするには、同じテストを複数回実行し、結果を平均値または中間値として集計します(以下では、この処理を「バッチ」と記載します)。これにより、テストのパフォーマンスの大まかな数字を、正確なタイミングを必要とすることなく取得できます。



</p>

<p>
  バッチは、コード変更の合間にも、それらの変更がパフォーマンスにもたらす相対的な影響を確認するために使用できます。
変更前のバッチの平均フレームレートが変更後のバッチよりも大きい場合、通常、WRT パフォーマンスが全面的に改善したと言えます。


</p>

<p>
  つまり、自動化された UI テストでは、この考え方を取り入れることと、テスト中に発生する可能性のある異常を把握しておくことが必要です。
たとえば、アプリケーションのパフォーマンスが、そのアプリケーションではなく何らかの端末の問題により突然低下した場合、通常時のタイミングを取得するためにバッチを再度実行した方がよいことがあります。



</p>

<p>
  それでは、測定値を意味のあるものにするには、何回テストを実行すればよいでしょうか。少なくとも 10 回は必要であり、50 回や 100 回などのように回数が多いほど正確な結果が得られます(もちろん、時間と正確さはトレードオフの関係にあります)。


</p>