Home | History | Annotate | Download | only in testing
      1 page.title=Testing Display Performance
      2 page.article=true
      3 page.image=images/cards/card-test-performance_2x.png
      4 page.keywords=performance, fps, tools
      5 
      6 @jd:body
      7 
      8 
      9 <div id="tb-wrapper">
     10   <div id="tb">
     11     <h2>In this document</h2>
     12       <ol>
     13         <li><a href="#measure">Measuring UI Performance</a>
     14           <ul>
     15             <li><a href="#aggregate">Aggregate frame stats</a></li>
     16             <li><a href="#timing-info">Precise frame timing info</a></li>
     17             <li><a href="#timing-dump">Simple frame timing dump</a></li>
     18             <li><a href="#collection-window">Controlling the window of stat collection</a></li>
     19             <li><a href="#diagnose">Diagnosing performance regressions</a></li>
     20             <li><a href="#resources">Additional resources</a></li>
     21           </ul>
     22         </li>
     23         <li><a href="#automate">Automating UI Perfomance Tests</a>
     24           <ul>
     25             <li><a href="#ui-tests">Setting up UI tests</a></li>
     26             <li><a href="#automated-tests">Setting up automated UI testing</a></li>
     27             <li><a href="#triage">Triaging and fixing observed problems</a></li>
     28           </ul>
     29         </li>
     30       </ol>
     31 
     32   </div>
     33 </div>
     34 
     35 
     36 <p>
     37   User interface (UI) performance testing ensures that your app not only meets its functional
     38   requirements, but that user interactions with your app are buttery smooth, running at a
     39   consistent 60 frames per second (<a href=
     40   "https://www.youtube.com/watch?v=CaMTIgxCSqU&index=25&list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">why
     41   60fps?</a>), without any dropped or delayed frames, or as we like to call it, <em>jank</em>. This
     42   document explains tools available to measure UI performance, and lays out an approach to
     43   integrate UI performance measurements into your testing practices.
     44 </p>
     45 
     46 
     47 <h2 id="measure">Measuring UI Performance</h2>
     48 
     49 <p>
     50   In order to improve performance you first need the ability to measure the performance of
     51   your system, and then diagnose and identify problems that may arrive from various parts of your
     52   pipeline.
     53 </p>
     54 
     55 <p>
     56   <em><a href="https://source.android.com/devices/tech/debug/dumpsys.html">dumpsys</a></em> is an
     57   Android tool that runs on the device and dumps interesting information about the status of system
     58   services. Passing the <em>gfxinfo</em> command to dumpsys provides an output in logcat with
     59   performance information relating to frames of animation that are occurring during the recording
     60   phase.
     61 </p>
     62 
     63 <pre>
     64 &gt; adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt;
     65 </pre>
     66 
     67 <p>
     68   This command can produce multiple different variants of frame timing data.
     69 </p>
     70 
     71 <h3 id="aggregate">Aggregate frame stats</h3>
     72 
     73 <p>
     74   With the M Preview the command prints out aggregated analysis of frame data to logcat, collected
     75   across the entire lifetime of the process. For example:
     76 </p>
     77 
     78 <pre class="noprettyprint">
     79 Stats since: 752958278148ns
     80 Total frames rendered: 82189
     81 Janky frames: 35335 (42.99%)
     82 90th percentile: 34ms
     83 95th percentile: 42ms
     84 99th percentile: 69ms
     85 Number Missed Vsync: 4706
     86 Number High input latency: 142
     87 Number Slow UI thread: 17270
     88 Number Slow bitmap uploads: 1542
     89 Number Slow draw: 23342
     90 </pre>
     91 
     92 <p>
     93   These high level statistics convey at a high level the rendering performance of the app, as well
     94   as its stability across many frames.
     95 </p>
     96 
     97 
     98 <h3 id="timing-info">Precise frame timing info</h3>
     99 
    100 <p>
    101   With the M Preview comes a new command for gfxinfo, and thats <em>framestats</em> which provides
    102   extremely detailed frame timing information from recent frames, so that you can track down and
    103   debug problems more accurately.
    104 </p>
    105 
    106 <pre>
    107 &gt;adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt; framestats
    108 </pre>
    109 
    110 <p>
    111   This command prints out frame timing information, with nanosecond timestamps, from the last 120
    112   frames produced by the app. Below is example raw output from adb dumpsys gfxinfo
    113   &lt;PACKAGE_NAME&gt; framestats:
    114 </p>
    115 
    116 <pre class="noprettyprint">
    117 0,27965466202353,27965466202353,27965449758000,27965461202353,27965467153286,27965471442505,27965471925682,27965474025318,27965474588547,27965474860786,27965475078599,27965479796151,27965480589068,
    118 0,27965482993342,27965482993342,27965465835000,27965477993342,27965483807401,27965486875630,27965487288443,27965489520682,27965490184380,27965490568703,27965491408078,27965496119641,27965496619641,
    119 0,27965499784331,27965499784331,27965481404000,27965494784331,27965500785318,27965503736099,27965504201151,27965506776568,27965507298443,27965507515005,27965508405474,27965513495318,27965514061984,
    120 0,27965516575320,27965516575320,27965497155000,27965511575320,27965517697349,27965521276151,27965521734797,27965524350474,27965524884536,27965525160578,27965526020891,27965531371203,27965532114484,
    121 </pre>
    122 
    123 <p>
    124   Each line of this output represents a frame produced by the app. Each line has a fixed number of
    125   columns describing time spent in each stage of the frame-producing pipeline. The next section
    126   describes this format in detail, including what each column represents.
    127 </p>
    128 
    129 
    130 <h4 id="fs-data-format">Framestats data format</h4>
    131 
    132 <p>
    133   Since the block of data is output in CSV format, it's very straightforward to paste it to your
    134   spreadsheet tool of choice, or collect and parse with a script. The following table explains the
    135   format of the output data columns. All timestamps are in nanoseconds.
    136 </p>
    137 
    138 <ul>
    139   <li>FLAGS
    140     <ul>
    141       <li>Rows with a 0 for the FLAGS column can have their total frame time computed by
    142       subtracting the INTENDED_VSYNC column from the FRAME_COMPLETED column.
    143       </li>
    144 
    145       <li>If this is non-zero the row should be ignored, as the frame has been determined as being
    146       an outlier from normal performance, where it is expected that layout &amp; draw take longer
    147       than 16ms. Here are a few reasons this could occur:
    148         <ul>
    149           <li>The window layout changed (such as the first frame of the application or after a
    150           rotation)
    151           </li>
    152 
    153           <li>It is also possible the frame was skipped in which case some of the values will have
    154           garbage timestamps. A frame can be skipped if for example it is out-running 60fps or if
    155           nothing on-screen ended up being dirty, this is not necessarily a sign of a problem in
    156           the app.
    157           </li>
    158         </ul>
    159       </li>
    160     </ul>
    161   </li>
    162 
    163   <li>INTENDED_VSYNC
    164     <ul>
    165       <li>The intended start point for the frame. If this value is different from VSYNC, there
    166       was work occurring on the UI thread that prevented it from responding to the vsync signal
    167       in a timely fashion.
    168       </li>
    169     </ul>
    170   </li>
    171 
    172   <li>VSYNC
    173     <ul>
    174       <li>The time value that was used in all the vsync listeners and drawing for the frame
    175       (Choreographer frame callbacks, animations, View.getDrawingTime(), etc)
    176       </li>
    177 
    178       <li>To understand more about VSYNC and how it influences your application, check out the
    179       <a href=
    180       "https://www.youtube.com/watch?v=1iaHxmfZGGc&list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&index=23">
    181         Understanding VSYNC</a> video.
    182       </li>
    183     </ul>
    184   </li>
    185 
    186   <li>OLDEST_INPUT_EVENT
    187     <ul>
    188       <li>The timestamp of the oldest input event in the input queue, or Long.MAX_VALUE if
    189       there were no input events for the frame.
    190       </li>
    191 
    192       <li>This value is primarily intended for platform work and has limited usefulness to app
    193       developers.
    194       </li>
    195     </ul>
    196   </li>
    197 
    198   <li>NEWEST_INPUT_EVENT
    199     <ul>
    200       <li>The timestamp of the newest input event in the input queue, or 0 if there were no
    201       input events for the frame.
    202       </li>
    203 
    204       <li>This value is primarily intended for platform work and has limited usefulness to app
    205       developers.
    206       </li>
    207 
    208       <li>However its possible to get a rough idea of how much latency the app is adding by
    209       looking at (FRAME_COMPLETED - NEWEST_INPUT_EVENT).
    210       </li>
    211     </ul>
    212   </li>
    213 
    214   <li>HANDLE_INPUT_START
    215     <ul>
    216       <li>The timestamp at which input events were dispatched to the application.
    217       </li>
    218 
    219       <li>By looking at the time between this and ANIMATION_START it is possible to measure how
    220       long the application spent handling input events.
    221       </li>
    222 
    223       <li>If this number is high (&gt;2ms), this indicates the app is spending an unusually
    224       long time processing input events, such as View.onTouchEvent(), which may indicate this
    225       work needs to be optimized, or offloaded to a different thread. Note that there are some
    226       scenarios, such as click events that launch new activities or similar, where it is
    227       expected and acceptable that this number is large.
    228       </li>
    229     </ul>
    230   </li>
    231 
    232   <li>ANIMATION_START
    233     <ul>
    234       <li>The timestamp at which animations registered with Choreographer were run.
    235       </li>
    236 
    237       <li>By looking at the time between this and PERFORM_TRANVERSALS_START it is possible to
    238       determine how long it took to evaluate all the animators (ObjectAnimator,
    239       ViewPropertyAnimator, and Transitions being the common ones) that are running.
    240       </li>
    241 
    242       <li>If this number is high (&gt;2ms), check to see if your app has written any custom
    243       animators or what fields ObjectAnimators are animating and ensure they are appropriate
    244       for an animation.
    245       </li>
    246 
    247       <li>To learn more about Choreographer, check out the <a href=
    248       "https://www.youtube.com/watch?v=Q8m9sHdyXnE">For Butter or Worse</a>
    249       video.
    250       </li>
    251     </ul>
    252   </li>
    253 
    254   <li>PERFORM_TRAVERSALS_START
    255     <ul>
    256       <li>If you subtract out DRAW_START from this value, you can extract how long the layout
    257       &amp; measure phases took to complete. (note, during a scroll, or animation, you would
    258       hope this should be close to zero..)
    259       </li>
    260 
    261       <li>To learn more about the measure &amp; layout phases of the rendering pipeline, check
    262       out the <a href=
    263       "https://www.youtube.com/watch?v=we6poP0kw6E&list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&index=27">
    264         Invalidations, Layouts and Performance</a> video
    265       </li>
    266     </ul>
    267   </li>
    268 
    269   <li>DRAW_START
    270     <ul>
    271       <li>The time at which the draw phase of performTraversals started. This is the start
    272       point of recording the display lists of any views that were invalidated.
    273       </li>
    274 
    275       <li>The time between this and SYNC_START is how long it took to call View.draw() on all
    276       the invalidated views in the tree.
    277       </li>
    278 
    279       <li>For more information on the drawing model, see <a href=
    280       "{@docRoot}guide/topics/graphics/hardware-accel.html#hardware-model">Hardware Acceleration</a>
    281       or the <a href=
    282       "https://www.youtube.com/watch?v=we6poP0kw6E&list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu&index=27">
    283         Invalidations, Layouts and Performance</a> video
    284       </li>
    285     </ul>
    286   </li>
    287 
    288   <li>SYNC_QUEUED
    289     <ul>
    290       <li>The time at which a sync request was sent to the RenderThread.
    291       </li>
    292 
    293       <li>This marks the point at which a message to start the sync
    294       phase was sent to the RenderThread. If the time between this and
    295       SYNC_START is substantial (&gt;0.1ms or so), it means that
    296       the RenderThread was busy working on a different frame. Internally
    297       this is used to differentiate between the frame doing too much work
    298       and exceeding the 16ms budget and the frame being stalled due to
    299       the previous frame exceeding the 16ms budget.
    300       </li>
    301     </ul>
    302   </li>
    303 
    304   <li>SYNC_START
    305     <ul>
    306       <li>The time at which the sync phase of the drawing started.
    307       </li>
    308 
    309       <li>If the time between this and ISSUE_DRAW_COMMANDS_START is substantial (&gt;0.4ms or
    310       so), it typically indicates a lot of new Bitmaps were drawn which must be uploaded to the
    311       GPU.
    312       </li>
    313 
    314       <li>To understand more about the sync phase, check out the <a href=
    315       "https://www.youtube.com/watch?v=VzYkVL1n4M8&index=24&list=PLOU2XLYxmsIKEOXh5TwZEv89aofHzNCiu">
    316         Profile GPU Rendering</a> video
    317       </li>
    318     </ul>
    319   </li>
    320 
    321   <li>ISSUE_DRAW_COMMANDS_START
    322     <ul>
    323       <li>The time at which the hardware renderer started issuing drawing commands to the GPU.
    324       </li>
    325 
    326       <li>The time between this and FRAME_COMPLETED gives a rough idea of how much GPU work the
    327       app is producing. Problems like too much overdraw or inefficient rendering effects show
    328       up here.
    329       </li>
    330     </ul>
    331   </li>
    332 
    333   <li>SWAP_BUFFERS
    334     <ul>
    335       <li>The time at which eglSwapBuffers was called, relatively uninteresting outside of
    336       platform work.
    337       </li>
    338     </ul>
    339   </li>
    340 
    341   <li>FRAME_COMPLETED
    342     <ul>
    343       <li>All done! The total time spent working on this frame can be computed by doing
    344       FRAME_COMPLETED - INTENDED_VSYNC.
    345       </li>
    346     </ul>
    347   </li>
    348 
    349 </ul>
    350 
    351 <p>
    352   You can use this data in different ways. One simple but useful visualization is a
    353   histogram showing the distribution of frames times (FRAME_COMPLETED - INTENDED_VSYNC) in
    354   different latency buckets, see figure below. This graph tells us at a glance that most
    355   frames were very good - well below the 16ms deadline (depicted in red), but a few frames
    356   were significantly over the deadline. We can look at changes in this histogram over time
    357   to see wholesale shifts or new outliers being created. You can also graph input latency,
    358   time spent in layout, or other similar interesting metrics based on the many timestamps
    359   in the data.
    360 </p>
    361 
    362 <img src="{@docRoot}images/performance-testing/perf-test-framestats.png">
    363 
    364 
    365 <h3 id="timing-dump">Simple frame timing dump</h3>
    366 
    367 <p>
    368   If <strong>Profile GPU rendering</strong> is set to <strong>In adb shell dumpsys gfxinfo</strong>
    369   in Developer Options, the <code>adb shell dumpsys gfxinfo</code> command prints out timing
    370   information for the most recent 120 frames, broken into a few different categories with
    371   tab-separated-values. This data can be useful for indicating which parts of the drawing pipeline
    372   may be slow at a high level.
    373 </p>
    374 
    375 <p>
    376   Similar to <a href="#fs-data-format">framestats</a> above, it's very
    377   straightforward to paste it to your spreadsheet tool of choice, or collect and parse with
    378   a script. The following graph shows a breakdown of where many frames produced by the app
    379   were spending their time.
    380 </p>
    381 
    382 <img src="{@docRoot}images/performance-testing/perf-test-frame-latency.png">
    383 
    384 <p>
    385   The result of running gfxinfo, copying the output, pasting it into a spreadsheet
    386   application, and graphing the data as stacked bars.
    387 </p>
    388 
    389 <p>
    390   Each vertical bar represents one frame of animation; its height represents the number of
    391   milliseconds it took to compute that frame of animation. Each colored segment of the bar
    392   represents a different stage of the rendering pipeline, so that you can see what parts of
    393   your application may be creating a bottleneck. For more information on understanding the
    394   rendering pipeline, and how to optimize for it, see the <a href=
    395   "https://www.youtube.com/watch?v=we6poP0kw6E&index=27&list=PLWz5rJ2EKKc9CBxr3BVjPTPoDPLdPIFCE">
    396   Invalidations Layouts and Performance</a> video.
    397 </p>
    398 
    399 
    400 <h3 id="collection-window">Controlling the window of stat collection</h3>
    401 
    402 <p>
    403   Both the framestats and simple frame timings gather data over a very short window - about
    404   two seconds worth of rendering. In order to precisely control this window of time - for
    405   example, to constrain the data to a particular animation - you can reset all counters,
    406   and aggregate statistics gathered.
    407 </p>
    408 
    409 <pre>
    410 &gt;adb shell dumpsys gfxinfo &lt;PACKAGE_NAME&gt; reset
    411 </pre>
    412 
    413 <p>
    414   This can also be used in conjunction with the dumping commands themselves to collect and
    415   reset at a regular cadence, capturing less-than-two-second windows of frames
    416   continuously.
    417 </p>
    418 
    419 
    420 <h3 id="diagnose">Diagnosing performance regressions</h3>
    421 
    422 <p>
    423   Identification of regressions is a good first step to tracking down problems, and
    424   maintaining high application health. However, dumpsys just identifies the existence and
    425   relative severity of problems. You still need to diagnose the particular cause of the
    426   performance problems, and find appropriate ways to fix them. For that, its highly
    427   recommended to use the <a href="{@docRoot}tools/help/systrace.html">systrace</a> tool.
    428 </p>
    429 
    430 
    431 <h3 id="resources">Additional resources</h3>
    432 
    433 <p>
    434   For more information on how Androids rendering pipeline works, common problems that you
    435   can find there, and how to fix them, some of the following resources may be useful to
    436   you:
    437 </p>
    438 
    439 <ul>
    440   <li>
    441     <a class="external-link" href="https://www.youtube.com/watch?v=HXQhu6qfTVU">
    442       Rendering Performance 101</a>
    443   </li>
    444   <li>
    445     <a class="external-link" href="https://www.youtube.com/watch?v=CaMTIgxCSqU">
    446       Why 60fps?</a>
    447   </li>
    448   <li>
    449     <a class="external-link" href="https://www.youtube.com/watch?v=WH9AFhgwmDw">
    450       Android, UI, and the GPU</a>
    451   </li>
    452   <li>
    453     <a class="external-link" href="https://www.youtube.com/watch?v=we6poP0kw6E">
    454       Invalidations, Layouts, and Performance</a>
    455   </li>
    456   <li>
    457     <a href="{@docRoot}studio/profile/systrace.html">
    458       Analyzing UI Performance with Systrace</a>
    459   </li>
    460 </ul>
    461 
    462 
    463 <h2 id="automate">Automating UI Perfomance Tests</h2>
    464 
    465 <p>
    466   One approach to UI Performance testing is to simply have a human tester perform a set of
    467   user operations on the target app, and either visually look for jank, or spend an very
    468   large amount of time using a tool-driven approach to find it. But this manual approach is
    469   fraught with peril - human ability to perceive frame rate changes varies tremendously,
    470   and this is also time consuming, tedious, and error prone.
    471 </p>
    472 
    473 <p>
    474   A more efficient approach is to log and analyze key performance metrics from automated UI
    475   tests. The Android M developer preview includes new logging capabilities which make it
    476   easy to determine the amount and severity of jank in your applications animations, and
    477   that can be used to build a rigorous process to determine your current performance and
    478   track future performance objectives.
    479 </p>
    480 
    481 <p>
    482   This article walks you through a recommended approach to using that data to automate your
    483   performance testing.
    484 </p>
    485 
    486 <p>
    487   This is mostly broken down into two key actions. Firstly, identifying what you're
    488   testing, and how youre testing it. and Secondly, setting up, and maintaining an
    489   automated testing environment.
    490 </p>
    491 
    492 
    493 <h3 id="ui-tests">Setting up UI tests</h3>
    494 
    495 <p>
    496   Before you can get started with automated testing, its important to determine a few high
    497   level decisions, in order to properly understand your test space, and needs you may have.
    498 </p>
    499 
    500 <h4>
    501   Identify key animations / flows to test
    502 </h4>
    503 
    504 <p>
    505   Remember that bad performance is most visible to users when it interrupts a smooth
    506   animation. As such, when identifying what types of UI actions to test for, its useful to
    507   focus on the key animations that users see most, or are most important to their
    508   experience. For example, here are some common scenarios that may be useful to identify:
    509 </p>
    510 
    511 <ul>
    512   <li>Scrolling a primary ListView or RecyclerView
    513   </li>
    514 
    515   <li>Animations during async wait cycles
    516   </li>
    517 
    518   <li>Any animation that may have bitmap loading / manipulation in it
    519   </li>
    520 
    521   <li>Animations including Alpha Blending
    522   </li>
    523 
    524   <li>Custom View drawing with Canvas
    525   </li>
    526 </ul>
    527 
    528 <p>
    529   Work with engineers, designers, and product managers on your team to prioritize these key
    530   product animations for test coverage.
    531 </p>
    532 
    533 <h4>
    534   Define your future objectives and track against them
    535 </h4>
    536 
    537 <p>
    538   From a high-level, it may be critical to identify your specific performance goals, and
    539   focus on writing tests, and collecting data around them. For example:
    540 </p>
    541 
    542 <ul>
    543   <li>Do you just want to begin tracking UI performance for the first time to learn more?
    544   </li>
    545 
    546   <li>Do you want to prevent regressions that might be introduced in the future?
    547   </li>
    548 
    549   <li>Are you at 90% of smooth frames today and want to get to 98% this quarter?
    550   </li>
    551 
    552   <li>Are you at 98% smooth frames and dont want to regress?
    553   </li>
    554 
    555   <li>Is your goal to improve performance on low end devices?
    556   </li>
    557 </ul>
    558 
    559 <p>
    560   In all of these cases, youll want historical tracking which shows performance across
    561   multiple versions of your application.
    562 </p>
    563 
    564 <h4>
    565   Identify devices to test on
    566 </h4>
    567 
    568 <p>
    569   Application performance varies depending on the device it's running on. Some devices may
    570   contain less memory, less powerful GPUs, or slower CPU chips. This means that animations
    571   which may perform well on one set of hardware, may not on others, and worse, may be a
    572   result of a bottleneck in a different part of the pipeline. So, to account for this
    573   variation in what a user might see, pick a range of devices to execute tests on, both
    574   current high end devices, low end devices, tablets, etc. Look for variation in CPU
    575   performance, RAM, screen density, size, and so on. Tests that pass on a high end device
    576   may fail on a low end device.
    577 </p>
    578 
    579 <h4>
    580   Basic frameworks for UI Testing
    581 </h4>
    582 
    583 <p>
    584   Tool suites, like <a href=
    585   "{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a> and
    586   <a href="{@docRoot}training/testing/ui-testing/espresso-testing.html">Espresso</a>, are
    587   built to help automate the action of a user moving through your application. These are simple
    588   frameworks which mimic user interaction with your device. To use these frameworks, you
    589   effectively create unique scripts, which run through a set of user-actions, and play them
    590   out on the device itself.
    591 </p>
    592 
    593 <p>
    594   By combining these automated tests, alongside <code>dumpsys gfxinfo</code> you can quickly
    595   create a reproducible system that allows you to execute a test, and measure the
    596   performance information of that particular condition.
    597 </p>
    598 
    599 
    600 <h3 id="automated-tests">Setting up automated UI testing</h3>
    601 
    602 <p>
    603   Once you have the ability to execute a UI test, and a pipeline to gather the data from a
    604   single test, the next important step is to embrace a framework which can execute that
    605   test multiple times, across multiple devices, and aggregate the resulting performance
    606   data for further analysis by your development team.
    607 </p>
    608 
    609 <h4>
    610   A framework for test automation
    611 </h4>
    612 
    613 <p>
    614   Its worth noting that UI testing frameworks (like <a href=
    615   "{@docRoot}training/testing/ui-testing/uiautomator-testing.html">UI Automator</a>)
    616   run on the target device/emulator directly. While performance gathering information done
    617   by <em>dumpsys gfxinfo</em> is driven by a host machine, sending commands over ADB. To
    618   help bridge the automation of these separate entities, <a href=
    619   "{@docRoot}tools/help/monkeyrunner_concepts.html">MonkeyRunner</a> framework was
    620   developed; A scripting system that runs on your host machine, which can issue commands to
    621   a set of connected devices, as well as receive data from them.
    622 </p>
    623 
    624 <p>
    625   Building a set of scripts for proper automation of UI Performance testing, at a minimum,
    626   should be able to utilize monkeyRunner to accomplish the following tasks:
    627 </p>
    628 
    629 <ul>
    630   <li>Load &amp; Launch a desired APK to a target device, devices, or emulator.
    631   </li>
    632 
    633   <li>Launch a UI Automator UI test, and allow it to be executed
    634   </li>
    635 
    636   <li>Collect performance information through <em>dumpsys gfxinfo</em><em>.</em>
    637   </li>
    638 
    639   <li>Aggregate information and display it back in a useful fashion to the developer.
    640   </li>
    641 </ul>
    642 
    643 
    644 <h3 id="triage">Triaging and fixing observed problems</h3>
    645 
    646 <p>
    647   Once problem patterns or regressions are identified, the next step is identifying and
    648   applying the fix. If your automated test framework preserves precise timing breakdowns
    649   for frames, it can help you scrutinize recent suspicious code/layout changes (in the case
    650   of regression), or narrow down the part of the system youre analyzing when you switch to
    651   manual investigation. For manual investigation, <a href=
    652   "{@docRoot}tools/help/systrace.html">systrace</a> is a great place to start, showing
    653   precise timing information about every stage of the rendering pipeline, every thread and
    654   core in the system, as well as any custom event markers you define.
    655 </p>
    656 
    657 <h4>
    658   Properly profiling temporal timings
    659 </h4>
    660 
    661 <p>
    662   It is important to note the difficulties in obtaining and measuring timings that come from
    663   rendering performance. These numbers are, by nature, non deterministic, and often
    664   fluctuate depending on the state of the system, amount of memory available, thermal
    665   throttling, and the last time a sun flare hit your area of the earth. The point is that
    666   you can run the same test, twice and get slightly different numbers that may be close to
    667   each other, but not exact.
    668 </p>
    669 
    670 <p>
    671   Properly gathering and profiling data in this manner means running the same test,
    672   multiple times, and accumulating the results as an average, or median value. (for the
    673   sake of simplicity, lets call this a batch) This gives you the rough approximation of
    674   the performance of the test, while not needing exact timings.
    675 </p>
    676 
    677 <p>
    678   Batches can be used between code changes to see the relative impact of those changes on
    679   performance. If the average frame rate for the pre-change Batch is larger than the
    680   post-change batch, then you generally have an overall win wrt performance for that
    681   particular change.
    682 </p>
    683 
    684 <p>
    685   This means that any Automated UI testing you do should take this concept into
    686   consideration, and also account for any anomalies that might occur during a test. For
    687   example, if your application performance suddenly dips, due to some device issue (that
    688   isnt caused by your application) then you may want to re-run the batch in order to get
    689   less chaotic timings.
    690 </p>
    691 
    692 <p>
    693   So, how many times should you run a test, before the measurements become meaningful? 10
    694   times should be the minimum, with higher numbers like 50 or 100 yielding more accurate
    695   results (of course, youre now trading off time for accuracy)
    696 </p>
    697