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
5import 'package:flutter/rendering.dart';
6
7import '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.
24class 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