summaryrefslogtreecommitdiffstats
path: root/docs/html-intl/intl/pt-br/preview/testing/performance.jd
blob: d541be11c0a7542cfc858f0edcf8f9ba686b9454 (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=Teste de desempenho de exibição
page.image=images/cards/card-test-performance_2x.png
page.keywords=performance, fps, tools

@jd:body


<div id="qv-wrapper">
  <div id="qv">
    <h2>Neste documento</h2>
      <ol>
        <li><a href="#measure">Medir desempenho da IU</a>
          <ul>
            <li><a href="#aggregate">Agregar estatísticas de quadro</a></li>
            <li><a href="#timing-info">Informações de precisão de quadro</a></li>
            <li><a href="#timing-dump">Despejo de precisão de quadro simples</a></li>
            <li><a href="#collection-window">Controlar janela de coleta de estatísticas</a></li>
            <li><a href="#diagnose">Diagnosticar regressões de desempenho</a></li>
            <li><a href="#resources">Recursos adicionais</a></li>
          </ul>
        </li>
        <li><a href="#automate">Automatizar teste de desempenho da IU</a>
          <ul>
            <li><a href="#ui-tests">Configurar testes da IU</a></li>
            <li><a href="#automated-tests">Configurar testes automatizados da IU</a></li>
            <li><a href="#triage">Triagem e resolução de problemas observados</a></li>
          </ul>
        </li>
      </ol>
  </div>
</div>


<p>
  O teste de desempenho da interface do usuário (IU) garante que o aplicativo
 não só esteja de acordo com os requisitos funcionais, como também que as interações de usuários
 sejam muito mais suaves, executando a 60 quadros por segundo de forma consistente (<a href="https://www.youtube.com/watch?v=CaMTIgxCSqU&amp;index=25&amp;list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">por que
 60 qps?</a>), sem nenhum quadro atrasado ou descartado ou, como gostamos de chamar, <em>"jank"</em>. Este documento explica as ferramentas disponíveis
 para medir o desempenho da IU e dispõe uma abordagem para integrar
 as medidas de desempenho de IU nas práticas de teste.
</p>


<h2 id="measure">Medir desempenho da IU</h2>

<p>
  Para aprimorar o desempenho, deve-se primeiro ter a habilidade de medir o desempenho
 do sistema e, em seguida, diagnosticar e identificar problemas que podem ocorrer
 em várias partes do processo.
</p>

<p>
  <em><a href="https://source.android.com/devices/tech/debug/dumpsys.html">dumpsys</a></em> é uma ferramenta
 do Android que é executada no dispositivo e despeja informações interessantes sobre o estado
 dos serviços do sistema. Passar o comando <em>gfxinfo</em> para dumpsys fornece uma saída no logcat
 com informações de desempenho relacionada aos quadros de animação que ocorrem
 durante a fase de registro.
</p>

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

<p>
  Este comando pode produzir diversas variáveis de dados de precisão de quadro.
</p>

<h3 id="aggregate">Agregar estatísticas de quadro</h3>

<p>
  Com o M Preview, o comando emite uma análise agregada dos dados de quadro para logcat,
 coletados em todo o ciclo de vida do processo. Por exemplo:
</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>
  Estas estatísticas de alto nível carregam um alto nível de desempenho de renderização do aplicativo,
 bem como a estabilidade em vários quadros.
</p>


<h3 id="timing-info">Informações de precisão de quadro</h3>

<p>
  Com o M Preview, há um novo comando para gfxinfo, o <em>framestats</em>, que fornece
 informações de precisão de quadros extremamente detalhadas dos quadros recentes para que você possa rastrear
 e depurar os problemas de forma mais precisa.
</p>

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

<p>
  Este comando emite informações de precisão de quadros, com marcações de data e hora, dos últimos 120
 quadros produzidos pelo aplicativo. Abaixo, há um exemplo de saída bruta das estatísticas
 de quadro de adb dumpsys gfxinfo &lt;PACKAGE_NAME&gt;:
</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>
  Cada linha desta saída representa um quadro produzido pelo aplicativo. Cada linha tem um número fixo
 de colunas que descrevem o tempo gasto em cada estágio do pipeline que produz quadros. A próxima seção descreve
 este formato com detalhes, incluindo o que cada coluna representa.
</p>


<h4 id="fs-data-format">Formato de dados de estatísticas de quadro</h4>

<p>
  Como o bloco de dados é a saída no formato CSV, basta colá-lo na ferramenta
 de planilha de sua escolha ou coletá-lo e analisá-lo com o script. A tabela a seguir explica o formato
 das colunas de dados de saída. Todas as marcações de data e hora estão em nanossegundos.
</p>

<ul>
  <li>SINALIZADORES
    <ul>
      <li>Linhas com ‘0’ para a coluna FLAGS podem ter o tempo total de quadros calculado
 subtraindo a coluna INTENDED_VSYNC da coluna FRAME_COMPLETED.
      </li>

      <li>Se for um número diferente de zero, a linha deverá ser ignorada, pois o quadro será determinado
 como exceção em comparação ao desempenho normal, onde espera-se que o layout e o desenho
 demorem mais do que 16 ms. Eis alguns motivos para que isto ocorra:
        <ul>
          <li>Layout da janela alterado (como o primeiro quadro do aplicativo
 ou após uma rotação)
          </li>

          <li>Também é possível que o quadro seja ignorado, quando alguns valores
 ainda terão marcações de data e hora de lixo. Um quadro pode ser ignorado se, por exemplo,
 estiver executando a 60 quadros por segundo ou se nada na tela estiver incorreto, o que não necessariamente
 é um sinal de problema no aplicativo.
          </li>
        </ul>
      </li>
    </ul>
  </li>

  <li>INTENDED_VSYNC
    <ul>
      <li>O ponto inicial planejado para o quadro. Se este valor for diferente de VSYNC,
 significa que há um trabalho ocorrendo no encadeamento da IU que não permitiu que ele respondesse
 ao sinal de vsync de forma precisa.
      </li>
    </ul>
  </li>

  <li>VSYNC
    <ul>
      <li>O valor de tempo foi usado em todos os escutadores vsync e no desenho para o quadro
 (retorno de chamada do quadro Choreographer, animações, View.getDrawingTime(), etc.)
      </li>

      <li>Para entender mais sobre VSYNC e como ele influencia o aplicativo, assista ao vídeo
 <a href="https://www.youtube.com/watch?v=1iaHxmfZGGc&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=23">
Entendimento do VSYNC</a>.
      </li>
    </ul>
  </li>

  <li>OLDEST_INPUT_EVENT
    <ul>
      <li>A marcação de data e hora do evento de entrada mais antigo na fila de entrada, ou Long.MAX_VALUE
 se não houver eventos de entrada para o quadro.
      </li>

      <li>Este valor é principalmente planejado para o trabalho da plataforma e tem utilidade limitada
 para desenvolvedores de aplicativos.
      </li>
    </ul>
  </li>

  <li>NEWEST_INPUT_EVENT
    <ul>
      <li>A marcação de data e hora do evento de entrada mais recente na fila de entrada
 ou 0 se não houver eventos de entrada para o quadro.
      </li>

      <li>Este valor é principalmente planejado para o trabalho da plataforma e tem utilidade limitada
 para desenvolvedores de aplicativos.
      </li>

      <li>No entanto, é possível ter uma breve ideia da quantidade de latência que o aplicativo
 está adicionado verificando (FRAME_COMPLETED - NEWEST_INPUT_EVENT).
      </li>
    </ul>
  </li>

  <li>HANDLE_INPUT_START
    <ul>
      <li>A marcação de data e hora em que os eventos de entrada foram despachados para o aplicativo.
      </li>

      <li>Ao olhar o horário entre isto e ANIMATION_START, é possível medir o tempo que o aplicativo
 gastou para lidar com os eventos de entrada.
      </li>

      <li>Se este número for alto (&gt; 2 ms), indica que o aplicativo está gastando
 tempo demais processando os eventos de entrada, como View.onTouchEvent(), o que pode indicar
 que este trabalho precisa ser otimizado ou descarregado para um encadeamento diferente. Observe que há algumas situações,
 como eventos de clique que iniciam novas atividades,
 em que é esperado e aceitável que este número seja grande.
      </li>
    </ul>
  </li>

  <li>ANIMATION_START
    <ul>
      <li>A marcação de data e hora em que as animações registradas com Choreographer foram executadas.
      </li>

      <li>Ao olhar para o tempo entre isto e PERFORM_TRANVERSALS_START,
 é possível determinar o tempo levado para avaliar todos os animadores
 (ObjectAnimator, ViewPropertyAnimator e Transitions sendo as mais comuns) que estão sendo executados.
      </li>

      <li>Se este número for alto (&gt; 2 ms), verifique se o aplicativo gravou qualquer animador
 personalizado ou quais campos de ObjectAnimators estão animando
 e certifique-se de que eles sejam adequados para uma animação.
      </li>

      <li>Para saber mais sobre Choreographer, assista ao vídeo
 <a href="https://developers.google.com/events/io/sessions/325418001">Para melhor ou pior</a>.
      </li>
    </ul>
  </li>

  <li>PERFORM_TRAVERSALS_START
    <ul>
      <li>Se você subtrair o DRAW_START deste valor, será possível extrair o tempo que as fases de medida e layout
 levaram para serem concluídas (observação: durante uma rolagem ou animação,
 espera-se que este valor seja próximo a zero).
      </li>

      <li>Para saber mais sobre as fases de medida e layout do pipeline de renderização,
 assista ao vídeo <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=27">
Invalidações, layouts e desempenho</a>
      </li>
    </ul>
  </li>

  <li>DRAW_START
    <ul>
      <li>O horário em que a fase de desenho de performTraversals foi iniciada. Este é o ponto inicial
 do registro de listas de exibição de vistas que foram invalidadas.
      </li>

      <li>O tempo entre isto e SYNC_START é o tempo levado para chamar View.draw()
 em todas as vistas invalidadas na árvore.
      </li>

      <li>Para obter mais informações sobre o modelo de desenho, assista aos vídeos <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#hardware-model">Aceleração de hardware</a>
 ou <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&amp;index=27">
 Invalidações, layouts e desempenho</a>
      </li>
    </ul>
  </li>

  <li>SYNC_START
    <ul>
      <li>O horário em que a fase de sincronização do desenho foi iniciada.
      </li>

      <li>Se o tempo entre isto e ISSUE_DRAW_COMMANDS_START for substancial (aproximadamente &gt; 0,4ms),
 geralmente indicará que vários Bitmaps novos que foram desenhados deverão
 ser enviados para o GPU.
      </li>

      <li>Para entender mais sobre a fase de sincronização, assista ao vídeo <a href="https://www.youtube.com/watch?v=VzYkVL1n4M8&amp;index=24&amp;list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu">
Renderização de GPU de perfil</a>
      </li>
    </ul>
  </li>

  <li>ISSUE_DRAW_COMMANDS_START
    <ul>
      <li>O horário em que o renderizador de hardware começou a emitir comandos de desenho para a GPU.
      </li>

      <li>O tempo entre isto e FRAME_COMPLETED fornece uma breve ideia da quantidade de trabalho de GPU
 que o aplicativo está produzindo. Problemas com excesso ou efeitos de renderização
 ineficientes são exibidos aqui.
      </li>
    </ul>
  </li>

  <li>SWAP_BUFFERS
    <ul>
      <li>O horário em que o eglSwapBuffers foi chamado, relativamente desinteressante
 fora do trabalho da plataforma.
      </li>
    </ul>
  </li>

  <li>FRAME_COMPLETED
    <ul>
      <li>Tudo feito! O tempo total gasto trabalhando neste quadro pode ser calculando
 realizando FRAME_COMPLETED - INTENDED_VSYNC.
      </li>
    </ul>
  </li>

</ul>

<p>
  É possível usar estes dados de várias formas. Uma visualização simples mas útil é o histograma
 exibindo a distribuição dos tempos dos quadros (FRAME_COMPLETED - INTENDED_VSYNC)
 em diferentes espaços de latência. Consulte a figura abaixo. Este gráfico mostra brevemente que a maioria
 dos quadros estavam bons — bem abaixo do limite de 16 ms (representado em vermelho) —,
 mas que alguns quadros estavam bem acima do limite. Podemos verificar as alterações neste histograma
 com o tempo para encontrar as mudanças indiscriminadas ou novas exceções sendo criadas. Também é possível colocar em gráfico a latência de entrada,
 o tempo gasto no layout ou outras medidas interessantes com base
 nas várias marcações de data e hora nos dados.
</p>

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


<h3 id="timing-dump">Despejo de precisão de quadro simples</h3>

<p>
  Se a <strong>renderização de GPU de perfil</strong> for definida para <strong>em adb shell dumpsys gfxinfo</strong>
 nas opções de desenvolvedor, o comando <code>adb shell dumpsys gfxinfo</code> emitirá informações
 de precisão para os 120 quadros mais recentes, divididas em algumas categorias
 com valores separados por guias. Estes dados podem ser úteis para indicar quais partes do pipeline
 de desenho podem estar lentas em um nível alto.
</p>

<p>
  Semelhante às <a href="#fs-data-format">estatísticas de quadro</a> acima,
 basta colá-los na ferramenta de planilha de sua escolha ou coletá-los e analisá-los
 com um script. O gráfico a seguir exibe um detalhamento de onde os vários quadros produzidos
 pelo aplicativo gastaram o tempo.
</p>

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

<p>
  O resultado de executar gfxinfo, copiar a saída, colá-lo no aplicativo de planilha
 e gerar um gráfico dos dados como barras empilhadas.
</p>

<p>
  Cada barra vertical representa um quadro da animação; sua altura representa a quantidade
 de milissegundos para calcular este quadro de animação. Cada segmento colorido da barra
 representa um estágio diferente do pipeline de renderização para que você possa ver que partes do aplicativo
 podem estar criando um afunilamento. Para obter mais informações sobre o entendimento do pipeline
 de renderização e como otimizá-lo, assista ao vídeo <a href="https://www.youtube.com/watch?v=we6poP0kw6E&amp;index=27&amp;list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">
Invalidações, layouts e desempenho</a>.
</p>


<h3 id="collection-window">Controlar janela de coleta de estatísticas</h3>

<p>
  As precisões de quadro simples e estatísticas de quadro coletam dados
 em um período muito curto — cerca de dois segundos de renderização. Para controlar este período de forma precisa — por exemplo,
 restringir os dados para uma animação em particular —, é possível redefinir
 todos os contadores e agregar as estatísticas coletadas.
</p>

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

<p>
  Isto também pode ser usado em conjunto com os próprios comandos de despejo para coletar
 e redefinir em uma cadência regular, capturando períodos de menos de dois segundos de quadros
 continuamente.
</p>


<h3 id="diagnose">Diagnosticar regressões de desempenho</h3>

<p>
  A identificação de regressões é uma boa primeira etapa para rastrear os problemas
 e manter o bem-estar do aplicativo. No entanto, o dumpsys identifica apenas a existência
 e a gravidade relativa dos problemas. Ainda é necessário diagnosticar a causa particular dos problemas
 de desempenho e encontrar maneiras adequadas de resolvê-los. Para isso, é altamente recomendado
 o uso da ferramenta <a href="{@docRoot}tools/help/systrace.html">systrace</a>.
</p>


<h3 id="resources">Recursos adicionais</h3>

<p>
  Para obter mais informações sobre como o pipeline de renderização do Android funciona,
 problemas comuns que podem ser encontrados e como resolvê-los,
 alguns dos seguintes recursos podem ser úteis:
</p>

<ul>
  <li>Desempenho de renderização 101
  </li>
  <li>Por que 60 qps?
  </li>
  <li>GPU e IU do Android
  </li>
  <li>Invalidações, layouts e desempenho
  </li>
  <li>Análise do desempenho de IU com Systrace
  </li>
</ul>


<h2 id="automate">Automatizar teste de desempenho da IU</h2>

<p>
  Uma abordagem para o teste de desempenho da IU é fazer com que um testador humano
 realize uma série de operações de usuário no aplicativo-alvo e procure visualmente problemas
 ou gaste uma grande quantidade de tempo usando uma abordagem de ferramenta para encontrá-los. No entanto, esta abordagem manual
 é repleta de riscos: a habilidade humana de notar alterações na taxa de quadros varia tremendamente,
 além de consumir tempo, ser tedioso e propenso a erros.
</p>

<p>
  Uma abordagem mais eficiente é registrar e analisar as métricas de desempenho essenciais
 dos testes de IU automatizados. O Android M Developer Preview inclui novas capacidades de registro que facilitam
 a determinação da quantidade e da gravidade de erros nas animações do aplicativo
 e que podem ser usadas para compilar um processo rigoroso para determinar o desempenho atual
 e rastrear os futuros objetivos de desempenho.
</p>

<p>
  Este artigo mostra uma abordagem recomendada para usar estes dados para automatizar
 o teste de desempenho.
</p>

<p>
  Ele é geralmente dividido em duas ações principais. Primeiro: identificar o que está testando
 e como será testado. Segundo: configuração e manutenção
 de um ambiente de teste automatizado.
</p>


<h3 id="ui-tests">Configurar de testes da IU</h3>

<p>
  Antes de iniciar o teste automatizado, é importante determinar algumas decisões de alto nível
 para entender corretamente o espaço de teste e as possíveis necessidades.
</p>

<h4>
  Identificar principais animações/fluxos a testar
</h4>

<p>
  Lembre-se que um desempenho ruim é mais visível aos usuários quando
 interrompe uma animação suave. Portanto, ao identificar que tipos de ações de IU serão testadas, é útil se concentrar
 nas animações principais que os usuários veem
 ou nas mais importantes para a experiência. Por exemplo, eis alguns cenários comuns que pode ser útil identificar:
</p>

<ul>
  <li>Rolagem de um ListView ou RecyclerView principal
  </li>

  <li>Animações durante ciclos de espera assíncrona
  </li>

  <li>Qualquer animação que possa ter manipulação ou carregamento de bitmap
  </li>

  <li>Animações com mistura alpha
  </li>

  <li>Desenho de vista personalizada com Canvas
  </li>
</ul>

<p>
  Trabalhe com engenheiros, designers, e gerentes de produto em sua equipe para priorizar
 as animações de produto essenciais para a cobertura de teste.
</p>

<h4>
  Defina os futuros objetivos e faça um rastreamento
</h4>

<p>
  De um alto nível, talvez seja essencial identificar os objetivos específicos de desempenho
 e concentrar-se em escrever testes e coletar dados. Por exemplo:
</p>

<ul>
  <li>Quer apenas iniciar o rastreamento de desempenho de IU pela primeira vez para aprender mais?
  </li>

  <li>Quer evitar regressões que possam ser introduzidas no futuro?
  </li>

  <li>Está com 90% de quadros suaves hoje e deseja chegar a 98% neste trimestre?
  </li>

  <li>Está com 98% de quadros suaves e não quer regredir?
  </li>

  <li>O seu objetivo é aprimorar o desempenho em dispositivos de baixo nível?
  </li>
</ul>

<p>
  Em todos esses casos, você optará pelo rastreamento histórico, que exibe o desempenho
 entre várias versões do aplicativo.
</p>

<h4>
  Identificar dispositivos para realizar testes
</h4>

<p>
  O desempenho do aplicativo varia dependendo do dispositivo em que está sendo executado. Alguns dispositivos podem
 conter menos memória, GPUs menos eficientes ou chips de CPU mais lentos. Isto significa que as animações que podem
 ter um bom desempenho em um conjunto de hardwares podem não ter o mesmo desempenho em outras,
 podendo ser o resultado de um afunilamento em uma parte diferente do pipeline. Portanto, para contabilizar
 esta variação em o que o usuário pode ver, escolha uma variação de dispositivos
 para executar os testes: dispositivos e tablets de alto e baixo nível etc. Procure variações no desempenho de CPU,
 RAM, densidade da tela, tamanho etc. Testes que passam em dispositivos de alto nível
 podem falhar em dispositivos de baixo nível.
</p>

<h4>
  Estruturas básicas para teste de IU
</h4>

<p>
  Conjuntos de ferramenta, como <a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a> e
 <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso</a>,
 são integrados para ajudar na automatização da ação de um usuário movendo-se pelo aplicativo. São estruturas simples
 que imitam a interação de usuário no dispositivo. Para usar estas estruturas,
 você cria efetivamente scripts únicos que executam um conjunto
 de ações de usuário e reproduzem-nas no próprio dispositivo.
</p>

<p>
  Ao combinar estes testes automatizados, juntamente com <code>dumpsys gfxinfo</code>, é possível criar
 rapidamente um sistema reproduzível que permite a execução de um teste e a medição das informações
 de desempenho desta condição em particular.
</p>


<h3 id="automated-tests">Configurar testes automatizados da IU</h3>

<p>
  Com a habilidade de executar um teste de IU e um pipeline para coletar
 os dados de um único teste, a próxima etapa importante é adotar uma estrutura que pode executar
 esse teste várias vezes, em vários dispositivos, e agregar os dados de desempenho resultados
 para futuras análises da equipe de desenvolvimento.
</p>

<h4>
  Uma estrutura para automatização de testes
</h4>

<p>
  Vale observar que as estruturas de teste de IU (como o <a href="{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a>)
 são executadas diretamente no emulador/dispositivo alvo. Enquanto as informações de coleta de desempenho feita
 pelo <em>dumpsys gfxinfo</em> forem direcionadas por uma máquina hospedeira, envie comandos pelo ADB. Para ajudar a transmitir
 a automatização dessas entidades separadas, a estrutura <a href="{@docRoot}tools/help/monkeyrunner_concepts.html">MonkeyRunner</a>
 foi desenvolvida: um sistema de script que é executado na máquina host que pode
 emitir comandos para um conjunto de dispositivos conectados, bem como receber dados deles.
</p>

<p>
  A compilação de um conjunto de scripts para uma automatização adequada de teste de desempenho de IU,
 no mínimo, deve ser capaz de utilizar o MonkeyRunner para realizar as seguintes tarefas:
</p>

<ul>
  <li>Carregar e iniciar um APK desejado para um emulador ou dispositivo alvo.
  </li>

  <li>Iniciar um teste de IU do UI Automator e permitir que ele seja executado.
  </li>

  <li>Coletar informações de desempenho por meio de <em>dumpsys gfxinfo</em><em>.</em>
  </li>

  <li>Agregar informações e exibi-las de forma útil para o desenvolvedor.
  </li>
</ul>


<h3 id="triage">Triagem e resolução de problemas observados</h3>

<p>
  Quando os padrões ou regressões dos problemas forem identificados, a próxima etapa
 é identificar e aplicar a resolução. Se a estrutura de teste automatizado preservar o detalhamento preciso para os quadros,
 ela poderá ajudar na inspeção de alterações de layout/código suspeitos recentes (em caso
 de regressão) ou reduzir a parte do sistema que você está analisando ao alternar
 para a investigação manual. Para a investigação manual, <a href="{@docRoot}tools/help/systrace.html">systrace</a> é um ótimo lugar para começar,
 exibindo as informações de precisão sobre cada estágio do pipeline de renderização,
 cada encadeamento e núcleo no sistema, bem como quaisquer marcadores de evento personalizados definidos.
</p>

<h4>
  Geração de perfis adequada de precisões temporais
</h4>

<p>
  É importante observar as dificuldades em obter e medir as precisões
 do desempenho de renderização. Esses números são, por natureza, não determinísticos e frequentemente
 oscilam dependendo do estado do sistema, da quantidade de memória disponível,
 da diminuição termal e da última vez em que a luz do sol atingiu a sua área da Terra. Ou seja, é possível executar
 o mesmo teste duas vezes e receber números levemente diferentes
 que podem ser muito próximos, mas não idênticos.
</p>

<p>
  A coleta e a geração de perfil de dados nesta maneira significa executar o mesmo teste,
 várias vezes, e acumular os resultados como uma média ou valor mediano (para a simplicidade,
 chamemos de "lote"). Isto fornece uma aproximação do desempenho do teste,
 já que precisões exatas não são necessárias.
</p>

<p>
  Os lotes podem ser usados entre alterações de códigos para verificar o impacto relativo
 dessas alterações no desempenho. Se a taxa de quadros média para o lote antes da alteração
 for maior do que o lote após a alteração, então o resultado de desempenho wrt geral será um sucesso
 para esta alteração em particular.
</p>

<p>
  Isto significa que qualquer teste de IU automatizado feito deve levar este conceito
 em consideração, bem como quaisquer anomalias que possam ocorrer durante um teste. Por exemplo,
 se o desempenho do aplicativo repentinamente cair devido a algum problema do dispositivo
 (que não tenha sido causado pelo aplicativo), então talvez seja necessário executar
 o lote novamente para obter precisões menos caóticas.
</p>

<p>
  Logo, quantas vezes deve-se realizar um teste antes de as medidas terem algum sentido? 10 vezes deve ser o mínimo,
 com números altos como 50 ou 10 oferecendo resultados mais precisos
 (é claro que se deve levar em consideração o tempo para ter mais precisão).
</p>