1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'package:flutter/rendering.dart'; |
6 | |
7 | import 'framework.dart'; |
8 | |
9 | /// Displays performance statistics. |
10 | /// |
11 | /// The overlay shows two time series. The first shows how much time was |
12 | /// required on this thread to produce each frame. The second shows how much |
13 | /// time was required on the raster thread (formerly known as the GPU thread) |
14 | /// to produce each frame. Ideally, both these values would be less than |
15 | /// the total frame budget for the hardware on which the app is running. |
16 | /// For example, if the hardware has a screen that updates at 60 Hz, each |
17 | /// thread should ideally spend less than 16ms producing each frame. |
18 | /// This ideal condition is indicated by a green vertical line for each thread. |
19 | /// Otherwise, the performance overlay shows a red vertical line. |
20 | /// |
21 | /// The simplest way to show the performance overlay is to set |
22 | /// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay] |
23 | /// to true. |
24 | class PerformanceOverlay extends LeafRenderObjectWidget { |
25 | // TODO(abarth): We should have a page on the web site with a screenshot and |
26 | // an explanation of all the various readouts. |
27 | |
28 | /// Create a performance overlay that only displays specific statistics. The |
29 | /// mask is created by shifting 1 by the index of the specific |
30 | /// [PerformanceOverlayOption] to enable. |
31 | const PerformanceOverlay({ |
32 | super.key, |
33 | this.optionsMask = 0, |
34 | this.rasterizerThreshold = 0, |
35 | this.checkerboardRasterCacheImages = false, |
36 | this.checkerboardOffscreenLayers = false, |
37 | }); |
38 | |
39 | /// Create a performance overlay that displays all available statistics. |
40 | PerformanceOverlay.allEnabled({ |
41 | super.key, |
42 | this.rasterizerThreshold = 0, |
43 | this.checkerboardRasterCacheImages = false, |
44 | this.checkerboardOffscreenLayers = false, |
45 | }) : optionsMask = |
46 | 1 << PerformanceOverlayOption.displayRasterizerStatistics.index | |
47 | 1 << PerformanceOverlayOption.visualizeRasterizerStatistics.index | |
48 | 1 << PerformanceOverlayOption.displayEngineStatistics.index | |
49 | 1 << PerformanceOverlayOption.visualizeEngineStatistics.index; |
50 | |
51 | /// The mask is created by shifting 1 by the index of the specific |
52 | /// [PerformanceOverlayOption] to enable. |
53 | final int optionsMask; |
54 | |
55 | /// The rasterizer threshold is an integer specifying the number of frame |
56 | /// intervals that the rasterizer must miss before it decides that the frame |
57 | /// is suitable for capturing an SkPicture trace for further analysis. |
58 | /// |
59 | /// For example, if you want a trace of all pictures that could not be |
60 | /// rendered by the rasterizer within the frame boundary (and hence caused |
61 | /// jank), specify 1. Specifying 2 will trace all pictures that took more |
62 | /// than 2 frame intervals to render. Adjust this value to only capture |
63 | /// the particularly expensive pictures while skipping the others. Specifying |
64 | /// 0 disables all capture. |
65 | /// |
66 | /// Captured traces are placed on your device in the application documents |
67 | /// directory in this form "trace_<collection_time>.skp". These can |
68 | /// be viewed in the Skia debugger. |
69 | /// |
70 | /// Notes: |
71 | /// The rasterizer only takes into account the time it took to render |
72 | /// the already constructed picture. This include the Skia calls (which is |
73 | /// also why an SkPicture trace is generated) but not any of the time spent in |
74 | /// dart to construct that picture. To profile that part of your code, use |
75 | /// the instrumentation available in observatory. |
76 | /// |
77 | /// To decide what threshold interval to use, count the number of horizontal |
78 | /// lines displayed in the performance overlay for the rasterizer (not the |
79 | /// engine). That should give an idea of how often frames are skipped (and by |
80 | /// how many frame intervals). |
81 | final int rasterizerThreshold; |
82 | |
83 | /// Whether the raster cache should checkerboard cached entries. |
84 | /// |
85 | /// The compositor can sometimes decide to cache certain portions of the |
86 | /// widget hierarchy. Such portions typically don't change often from frame to |
87 | /// frame and are expensive to render. This can speed up overall rendering. However, |
88 | /// there is certain upfront cost to constructing these cache entries. And, if |
89 | /// the cache entries are not used very often, this cost may not be worth the |
90 | /// speedup in rendering of subsequent frames. If the developer wants to be certain |
91 | /// that populating the raster cache is not causing stutters, this option can be |
92 | /// set. Depending on the observations made, hints can be provided to the compositor |
93 | /// that aid it in making better decisions about caching. |
94 | final bool checkerboardRasterCacheImages; |
95 | |
96 | /// Whether the compositor should checkerboard layers that are rendered to offscreen |
97 | /// bitmaps. This can be useful for debugging rendering performance. |
98 | /// |
99 | /// Render target switches are caused by using opacity layers (via a [FadeTransition] or |
100 | /// [Opacity] widget), clips, shader mask layers, etc. Selecting a new render target |
101 | /// and merging it with the rest of the scene has a performance cost. This can sometimes |
102 | /// be avoided by using equivalent widgets that do not require these layers (for example, |
103 | /// replacing an [Opacity] widget with an [widgets.Image] using a [BlendMode]). |
104 | final bool checkerboardOffscreenLayers; |
105 | |
106 | @override |
107 | RenderPerformanceOverlay createRenderObject(BuildContext context) => RenderPerformanceOverlay( |
108 | optionsMask: optionsMask, |
109 | rasterizerThreshold: rasterizerThreshold, |
110 | checkerboardRasterCacheImages: checkerboardRasterCacheImages, |
111 | checkerboardOffscreenLayers: checkerboardOffscreenLayers, |
112 | ); |
113 | |
114 | @override |
115 | void updateRenderObject(BuildContext context, RenderPerformanceOverlay renderObject) { |
116 | renderObject |
117 | ..optionsMask = optionsMask |
118 | ..rasterizerThreshold = rasterizerThreshold |
119 | ..checkerboardRasterCacheImages = checkerboardRasterCacheImages |
120 | ..checkerboardOffscreenLayers = checkerboardOffscreenLayers; |
121 | } |
122 | } |
123 | |