| // Copyright 2014 The Flutter Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'package:flutter/rendering.dart'; |
| |
| import 'framework.dart'; |
| |
| /// Displays performance statistics. |
| /// |
| /// The overlay shows two time series. The first shows how much time was |
| /// required on this thread to produce each frame. The second shows how much |
| /// time was required on the raster thread (formerly known as the GPU thread) |
| /// to produce each frame. Ideally, both these values would be less than |
| /// the total frame budget for the hardware on which the app is running. |
| /// For example, if the hardware has a screen that updates at 60 Hz, each |
| /// thread should ideally spend less than 16ms producing each frame. |
| /// This ideal condition is indicated by a green vertical line for each thread. |
| /// Otherwise, the performance overlay shows a red vertical line. |
| /// |
| /// The simplest way to show the performance overlay is to set |
| /// [MaterialApp.showPerformanceOverlay] or [WidgetsApp.showPerformanceOverlay] |
| /// to true. |
| class PerformanceOverlay extends LeafRenderObjectWidget { |
| // TODO(abarth): We should have a page on the web site with a screenshot and |
| // an explanation of all the various readouts. |
| |
| /// Create a performance overlay that only displays specific statistics. The |
| /// mask is created by shifting 1 by the index of the specific |
| /// [PerformanceOverlayOption] to enable. |
| const PerformanceOverlay({ |
| super.key, |
| this.optionsMask = 0, |
| this.rasterizerThreshold = 0, |
| this.checkerboardRasterCacheImages = false, |
| this.checkerboardOffscreenLayers = false, |
| }); |
| |
| /// Create a performance overlay that displays all available statistics. |
| PerformanceOverlay.allEnabled({ |
| super.key, |
| this.rasterizerThreshold = 0, |
| this.checkerboardRasterCacheImages = false, |
| this.checkerboardOffscreenLayers = false, |
| }) : optionsMask = |
| 1 << PerformanceOverlayOption.displayRasterizerStatistics.index | |
| 1 << PerformanceOverlayOption.visualizeRasterizerStatistics.index | |
| 1 << PerformanceOverlayOption.displayEngineStatistics.index | |
| 1 << PerformanceOverlayOption.visualizeEngineStatistics.index; |
| |
| /// The mask is created by shifting 1 by the index of the specific |
| /// [PerformanceOverlayOption] to enable. |
| final int optionsMask; |
| |
| /// The rasterizer threshold is an integer specifying the number of frame |
| /// intervals that the rasterizer must miss before it decides that the frame |
| /// is suitable for capturing an SkPicture trace for further analysis. |
| /// |
| /// For example, if you want a trace of all pictures that could not be |
| /// rendered by the rasterizer within the frame boundary (and hence caused |
| /// jank), specify 1. Specifying 2 will trace all pictures that took more |
| /// than 2 frame intervals to render. Adjust this value to only capture |
| /// the particularly expensive pictures while skipping the others. Specifying |
| /// 0 disables all capture. |
| /// |
| /// Captured traces are placed on your device in the application documents |
| /// directory in this form "trace_<collection_time>.skp". These can |
| /// be viewed in the Skia debugger. |
| /// |
| /// Notes: |
| /// The rasterizer only takes into account the time it took to render |
| /// the already constructed picture. This include the Skia calls (which is |
| /// also why an SkPicture trace is generated) but not any of the time spent in |
| /// dart to construct that picture. To profile that part of your code, use |
| /// the instrumentation available in observatory. |
| /// |
| /// To decide what threshold interval to use, count the number of horizontal |
| /// lines displayed in the performance overlay for the rasterizer (not the |
| /// engine). That should give an idea of how often frames are skipped (and by |
| /// how many frame intervals). |
| final int rasterizerThreshold; |
| |
| /// Whether the raster cache should checkerboard cached entries. |
| /// |
| /// The compositor can sometimes decide to cache certain portions of the |
| /// widget hierarchy. Such portions typically don't change often from frame to |
| /// frame and are expensive to render. This can speed up overall rendering. However, |
| /// there is certain upfront cost to constructing these cache entries. And, if |
| /// the cache entries are not used very often, this cost may not be worth the |
| /// speedup in rendering of subsequent frames. If the developer wants to be certain |
| /// that populating the raster cache is not causing stutters, this option can be |
| /// set. Depending on the observations made, hints can be provided to the compositor |
| /// that aid it in making better decisions about caching. |
| final bool checkerboardRasterCacheImages; |
| |
| /// Whether the compositor should checkerboard layers that are rendered to offscreen |
| /// bitmaps. This can be useful for debugging rendering performance. |
| /// |
| /// Render target switches are caused by using opacity layers (via a [FadeTransition] or |
| /// [Opacity] widget), clips, shader mask layers, etc. Selecting a new render target |
| /// and merging it with the rest of the scene has a performance cost. This can sometimes |
| /// be avoided by using equivalent widgets that do not require these layers (for example, |
| /// replacing an [Opacity] widget with an [widgets.Image] using a [BlendMode]). |
| final bool checkerboardOffscreenLayers; |
| |
| @override |
| RenderPerformanceOverlay createRenderObject(BuildContext context) => RenderPerformanceOverlay( |
| optionsMask: optionsMask, |
| rasterizerThreshold: rasterizerThreshold, |
| checkerboardRasterCacheImages: checkerboardRasterCacheImages, |
| checkerboardOffscreenLayers: checkerboardOffscreenLayers, |
| ); |
| |
| @override |
| void updateRenderObject(BuildContext context, RenderPerformanceOverlay renderObject) { |
| renderObject |
| ..optionsMask = optionsMask |
| ..rasterizerThreshold = rasterizerThreshold |
| ..checkerboardRasterCacheImages = checkerboardRasterCacheImages |
| ..checkerboardOffscreenLayers = checkerboardOffscreenLayers; |
| } |
| } |