// 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 'percentile_utils.dart'; import 'timeline.dart'; /// Key for SceneDisplayLag timeline events. const String kSceneDisplayLagEvent = 'SceneDisplayLag'; const String _kVsyncTransitionsMissed = 'vsync_transitions_missed'; /// Summarizes [TimelineEvents]s corresponding to [kSceneDisplayLagEvent] events. /// /// A sample event (some fields have been omitted for brevity): /// ``` /// { /// "name": "SceneDisplayLag", /// "ts": 408920509340, /// "ph": "b", (this can be 'b' or 'e' for begin or end) /// "args": { /// "frame_target_time": "408920509340458", /// "current_frame_target_time": "408920542689291", /// "vsync_transitions_missed": "2" /// } /// }, /// ``` /// /// `vsync_transitions_missed` corresponds to the elapsed number of frame budget /// durations between when the frame was scheduled to be displayed, i.e, the /// `frame_target_time` and the next vsync pulse timestamp, i.e, the /// `current_frame_target_time`. class SceneDisplayLagSummarizer { /// Creates a SceneDisplayLagSummarizer given the timeline events. SceneDisplayLagSummarizer(this.sceneDisplayLagEvents) { for (final TimelineEvent event in sceneDisplayLagEvents) { assert(event.name == kSceneDisplayLagEvent); } } /// The scene display lag events. final List<TimelineEvent> sceneDisplayLagEvents; /// Computes the average of the `vsync_transitions_missed` over the lag events. double computeAverageVsyncTransitionsMissed() { if (sceneDisplayLagEvents.isEmpty) { return 0; } final double total = sceneDisplayLagEvents .map(_getVsyncTransitionsMissed) .reduce((double a, double b) => a + b); return total / sceneDisplayLagEvents.length; } /// The [percentile]-th percentile `vsync_transitions_missed` over the lag events. double computePercentileVsyncTransitionsMissed(double percentile) { if (sceneDisplayLagEvents.isEmpty) { return 0; } final List<double> doubles = sceneDisplayLagEvents.map(_getVsyncTransitionsMissed).toList(); return findPercentile(doubles, percentile); } double _getVsyncTransitionsMissed(TimelineEvent e) { assert(e.name == kSceneDisplayLagEvent); assert(e.arguments!.containsKey(_kVsyncTransitionsMissed)); final dynamic transitionsMissed = e.arguments![_kVsyncTransitionsMissed]; assert(transitionsMissed is String); return double.parse(transitionsMissed as String); } }