diff --git a/lib/ui/hooks.dart b/lib/ui/hooks.dart index 02df73f7fe329..9c596c2e26008 100644 --- a/lib/ui/hooks.dart +++ b/lib/ui/hooks.dart @@ -198,7 +198,7 @@ void _reportTimings(List timings) { for (int i = 0; i < timings.length; i += FramePhase.values.length) { frameTimings.add(FrameTiming(timings.sublist(i, i + FramePhase.values.length))); } - _invoke1(window._onReportTimings, window._onReportTimingsZone, frameTimings); + _invoke1(window.onReportTimings, window._onReportTimingsZone, frameTimings); } @pragma('vm:entry-point') diff --git a/lib/ui/window.dart b/lib/ui/window.dart index d157ee946d694..a810551e38254 100644 --- a/lib/ui/window.dart +++ b/lib/ui/window.dart @@ -10,18 +10,17 @@ typedef VoidCallback = void Function(); /// Signature for [Window.onBeginFrame]. typedef FrameCallback = void Function(Duration duration); -// ignore: deprecated_member_use_from_same_package /// Signature for [Window.onReportTimings]. /// -/// The callback takes a list of [FrameTiming] because it may not be immediately -/// triggered after each frame. The list is sorted in ascending order of time -/// (earliest frame first). -/// {@template dart.ui.timings_batching} -/// Flutter tries to batch frames together and send all their timings at once to -/// decrease the overhead (as this is available in the release mode). The timing -/// of any frame will be sent within about 1 second (100ms if in the -/// profile/debug mode) even if there are no later frames to batch. The timing -/// of the first frame will be sent immediately without batching. +/// {@template dart.ui.TimingsCallback.list} +/// The callback takes a list of [FrameTiming] because it may not be +/// immediately triggered after each frame. Instead, Flutter tries to batch +/// frames together and send all their timings at once to decrease the +/// overhead (as this is available in the release mode). The list is sorted in +/// ascending order of time (earliest frame first). The timing of any frame +/// will be sent within about 1 second (100ms if in the profile/debug mode) +/// even if there are no later frames to batch. The timing of the first frame +/// will be sent immediately without batching. /// {@endtemplate} typedef TimingsCallback = void Function(List timings); @@ -70,7 +69,7 @@ enum FramePhase { /// Time-related performance metrics of a frame. /// -/// See [Window.frameTimings] for how to get this. +/// See [Window.onReportTimings] for how to get this. /// /// The metrics in debug mode (`flutter run` without any flags) may be very /// different from those in profile and release modes due to the debug overhead. @@ -83,7 +82,7 @@ class FrameTiming { /// [FramePhase.values]. /// /// This constructor is usually only called by the Flutter engine, or a test. - /// To get the [FrameTiming] of your app, see [Window.frameTimings]. + /// To get the [FrameTiming] of your app, see [Window.onReportTimings]. FrameTiming(List timestamps) : assert(timestamps.length == FramePhase.values.length), _timestamps = timestamps; @@ -934,17 +933,24 @@ class Window { /// A callback that is invoked to report the [FrameTiming] of recently /// rasterized frames. /// - /// This is deprecated, use [frameTimings] instead. - @Deprecated('Use frameTimings instead.') + /// This can be used to see if the application has missed frames (through + /// [FrameTiming.buildDuration] and [FrameTiming.rasterDuration]), or high + /// latencies (through [FrameTiming.totalSpan]). + /// + /// Unlike [Timeline], the timing information here is available in the release + /// mode (additional to the profile and the debug mode). Hence this can be + /// used to monitor the application's performance in the wild. + /// + /// {@macro dart.ui.TimingsCallback.list} + /// + /// If this is null, no additional work will be done. If this is not null, + /// Flutter spends less than 0.1ms every 1 second to report the timings + /// (measured on iPhone6S). The 0.1ms is about 0.6% of 16ms (frame budget for + /// 60fps), or 0.01% CPU usage per second. TimingsCallback get onReportTimings => _onReportTimings; TimingsCallback _onReportTimings; Zone _onReportTimingsZone; - @Deprecated('Use frameTimings instead.') set onReportTimings(TimingsCallback callback) { - _internalSetOnReportTimings(callback); - } - - void _internalSetOnReportTimings(TimingsCallback callback) { if ((callback == null) != (_onReportTimings == null)) { _setNeedsReportTimings(callback != null); } @@ -952,59 +958,6 @@ class Window { _onReportTimingsZone = Zone.current; } - // ignore: deprecated_member_use_from_same_package - /// Mock the calling of [onReportTimings] for unit tests. - void debugReportTimings(List timings) { - _onReportTimings(timings); - } - - /// Check whether the engine has to report timings. - /// - /// This is for unit tests and debug purposes only. - bool get debugNeedsReportTimings => _onReportTimings != null; - - StreamController _frameTimingBroadcastController; - - void _onFrameTimingListen() { - _internalSetOnReportTimings((List timings) { - timings.forEach(_frameTimingBroadcastController.add); - }); - } - - // If there's no one listening, set [onReportTimings] back to null so the - // engine won't send [FrameTiming] from engine to the framework. - void _onFrameTimingCancel() { - _internalSetOnReportTimings(null); - } - - /// A broadcast stream of the frames' time-related performance metrics. - /// - /// This can be used to see if the application has missed frames (through - /// [FrameTiming.buildDuration] and [FrameTiming.rasterDuration]), or high - /// latencies (through [FrameTiming.totalSpan]). - /// - /// Unlike [Timeline], the timing information here is available in the release - /// mode (additional to profile and debug mode). Hence this can be used to - /// monitor the application's performance in the wild. - /// - /// {@macro dart.ui.timings_batching} - /// - /// If no one is listening to this stream, no additional work will be done. - /// Otherwise, Flutter spends less than 0.1ms every 1 second to report the - /// timings (measured on iPhone 6s). The 0.1ms is about 0.6% of 16ms (frame - /// budget for 60fps), or 0.01% CPU usage per second. - /// - /// See also: - /// - /// * [FrameTiming], the data event of this stream - Stream get frameTimings { - _frameTimingBroadcastController ??= StreamController.broadcast( - onListen: _onFrameTimingListen, - onCancel: _onFrameTimingCancel, - ); - return _frameTimingBroadcastController.stream; - } - _SetNeedsReportTimingsFunc _setNeedsReportTimings; void _nativeSetNeedsReportTimings(bool value) native 'Window_setNeedsReportTimings'; diff --git a/lib/web_ui/lib/src/ui/window.dart b/lib/web_ui/lib/src/ui/window.dart index 567515595fc45..bf3183786384c 100644 --- a/lib/web_ui/lib/src/ui/window.dart +++ b/lib/web_ui/lib/src/ui/window.dart @@ -16,19 +16,7 @@ typedef VoidCallback = void Function(); /// common time base. typedef FrameCallback = void Function(Duration duration); -// ignore: deprecated_member_use_from_same_package /// Signature for [Window.onReportTimings]. -/// -/// The callback takes a list of [FrameTiming] because it may not be immediately -/// triggered after each frame. The list is sorted in ascending order of time -/// (earliest frame first). -/// {@template dart.ui.timings_batching} -/// Flutter tries to batch frames together and send all their timings at once to -/// decrease the overhead (as this is available in the release mode). The timing -/// of any frame will be sent within about 1 second (100ms if in the -/// profile/debug mode) even if there are no later frames to batch. The timing -/// of the first frame will be sent immediately without batching. -/// {@endtemplate} typedef TimingsCallback = void Function(List timings); /// Signature for [Window.onPointerDataPacket]. @@ -782,70 +770,24 @@ abstract class Window { /// A callback that is invoked to report the [FrameTiming] of recently /// rasterized frames. /// - /// This is deprecated, use [frameTimings] instead. - @Deprecated('Use frameTimings instead.') - TimingsCallback get onReportTimings => _onReportTimings; - TimingsCallback _onReportTimings; - @Deprecated('Use frameTimings instead.') - set onReportTimings(TimingsCallback callback) { - _internalSetOnReportTimings(callback); - } - - void _internalSetOnReportTimings(TimingsCallback callback) { - _onReportTimings = callback; - } - - // ignore: deprecated_member_use_from_same_package - /// Mock the calling of [onReportTimings] for unit tests. - void debugReportTimings(List timings) { - _onReportTimings(timings); - } - - /// Check whether the engine has to report timings. - /// - /// This is for unit tests and debug purposes only. - bool get debugNeedsReportTimings => _onReportTimings != null; - - StreamController _frameTimingBroadcastController; - - void _onFrameTimingListen() { - _internalSetOnReportTimings((List timings) { - timings.forEach(_frameTimingBroadcastController.add); - }); - } - - // If there's no one listening, set [onReportTimings] back to null so the - // engine won't send [FrameTiming] from engine to the framework. - void _onFrameTimingCancel() { - _internalSetOnReportTimings(null); - } - - /// A broadcast stream of the frames' time-related performance metrics. - /// /// This can be used to see if the application has missed frames (through /// [FrameTiming.buildDuration] and [FrameTiming.rasterDuration]), or high /// latencies (through [FrameTiming.totalSpan]). /// /// Unlike [Timeline], the timing information here is available in the release - /// mode (additional to profile and debug mode). Hence this can be used to - /// monitor the application's performance in the wild. - /// - /// {@macro dart.ui.timings_batching} - /// - /// If no one is listening to this stream, no additional work will be done. - /// Otherwise, Flutter spends less than 0.1ms every 1 second to report the - /// timings (measured on iPhone 6s). The 0.1ms is about 0.6% of 16ms (frame - /// budget for 60fps), or 0.01% CPU usage per second. - /// - /// See also: - /// - /// * [FrameTiming], the data event of this stream - Stream get frameTimings { - _frameTimingBroadcastController ??= StreamController.broadcast( - onListen: _onFrameTimingListen, - onCancel: _onFrameTimingCancel, - ); - return _frameTimingBroadcastController.stream; + /// mode (additional to the profile and the debug mode). Hence this can be + /// used to monitor the application's performance in the wild. + /// + /// The callback may not be immediately triggered after each frame. Instead, + /// it tries to batch frames together and send all their timings at once to + /// decrease the overhead (as this is available in the release mode). The + /// timing of any frame will be sent within about 1 second even if there are + /// no later frames to batch. + TimingsCallback get onReportTimings => _onReportTimings; + TimingsCallback _onReportTimings; + Zone _onReportTimingsZone; + set onReportTimings(TimingsCallback callback) { + _onReportTimings = callback; } /// A callback that is invoked for each frame after [onBeginFrame] has @@ -1226,7 +1168,7 @@ enum FramePhase { /// Time-related performance metrics of a frame. /// -/// See [Window.frameTimings] for how to get this. +/// See [Window.onReportTimings] for how to get this. /// /// The metrics in debug mode (`flutter run` without any flags) may be very /// different from those in profile and release modes due to the debug overhead. @@ -1239,15 +1181,17 @@ class FrameTiming { /// [FramePhase.values]. /// /// This constructor is usually only called by the Flutter engine, or a test. - /// To get the [FrameTiming] of your app, see [Window.frameTimings]. + /// To get the [FrameTiming] of your app, see [Window.onReportTimings]. FrameTiming(List timestamps) - : assert(timestamps.length == FramePhase.values.length), _timestamps = timestamps; + : assert(timestamps.length == FramePhase.values.length), + _timestamps = timestamps; /// This is a raw timestamp in microseconds from some epoch. The epoch in all /// [FrameTiming] is the same, but it may not match [DateTime]'s epoch. int timestampInMicroseconds(FramePhase phase) => _timestamps[phase.index]; - Duration _rawDuration(FramePhase phase) => Duration(microseconds: _timestamps[phase.index]); + Duration _rawDuration(FramePhase phase) => + Duration(microseconds: _timestamps[phase.index]); /// The duration to build the frame on the UI thread. /// @@ -1264,13 +1208,17 @@ class FrameTiming { /// {@template dart.ui.FrameTiming.fps_milliseconds} /// That's about 16ms for 60fps, and 8ms for 120fps. /// {@endtemplate} - Duration get buildDuration => _rawDuration(FramePhase.buildFinish) - _rawDuration(FramePhase.buildStart); + Duration get buildDuration => + _rawDuration(FramePhase.buildFinish) - + _rawDuration(FramePhase.buildStart); /// The duration to rasterize the frame on the GPU thread. /// /// {@macro dart.ui.FrameTiming.fps_smoothness_milliseconds} /// {@macro dart.ui.FrameTiming.fps_milliseconds} - Duration get rasterDuration => _rawDuration(FramePhase.rasterFinish) - _rawDuration(FramePhase.rasterStart); + Duration get rasterDuration => + _rawDuration(FramePhase.rasterFinish) - + _rawDuration(FramePhase.rasterStart); /// The timespan between build start and raster finish. /// @@ -1279,9 +1227,11 @@ class FrameTiming { /// {@macro dart.ui.FrameTiming.fps_milliseconds} /// /// See also [buildDuration] and [rasterDuration]. - Duration get totalSpan => _rawDuration(FramePhase.rasterFinish) - _rawDuration(FramePhase.buildStart); + Duration get totalSpan => + _rawDuration(FramePhase.rasterFinish) - + _rawDuration(FramePhase.buildStart); - final List _timestamps; // in microseconds + final List _timestamps; // in microseconds String _formatMS(Duration duration) => '${duration.inMicroseconds * 0.001}ms'; diff --git a/testing/dart/window_test.dart b/testing/dart/window_test.dart index 33e68013183c8..6a4ed12bbcefc 100644 --- a/testing/dart/window_test.dart +++ b/testing/dart/window_test.dart @@ -24,42 +24,4 @@ void main() { FrameTiming timing = FrameTiming([1000, 8000, 9000, 19500]); expect(timing.toString(), 'FrameTiming(buildDuration: 7.0ms, rasterDuration: 10.5ms, totalSpan: 18.5ms)'); }); - - test('window.frameTimings works', () async { - // Test a single subscription. Check that debugNeedsReportTimings is - // properly reset after the subscription is cancelled. - expect(window.debugNeedsReportTimings, false); - final FrameTiming mockTiming = FrameTiming([1000, 8000, 9000, 19500]); - final Future frameTiming = window.frameTimings.first; - expect(window.debugNeedsReportTimings, true); - window.debugReportTimings([mockTiming]); - expect(await frameTiming, equals(mockTiming)); - expect(window.debugNeedsReportTimings, false); - - // Test multiple (two) subscriptions after that debugNeedsReportTimings has - // been reset to false by the single subscription test above. - // - // Subscription 1 - final Future timingFuture = window.frameTimings.first; - // - // Subscription 2 - final List timings = []; - final Completer completer = Completer(); - int frameCount = 0; - window.frameTimings.listen((FrameTiming t) { - timings.add(t); - frameCount += 1; - if (frameCount == 2) { - completer.complete(); - } - }); - - final FrameTiming secondMock = FrameTiming([1, 2, 3, 4]); - window.debugReportTimings([secondMock, secondMock]); - final FrameTiming timing = await timingFuture; - expect(timing != mockTiming, isTrue); - expect(timing, equals(secondMock)); - await completer.future; - expect(timings, hasLength(2)); - }); }