mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Track the worst frame in perf tests (#3642)
* Track the worst frame in perf tests * Use backticks in "/// Returns `null` if"
This commit is contained in:
parent
4b6af7a42f
commit
4b401a3e75
@ -1611,7 +1611,7 @@ abstract class RenderObject extends AbstractNode implements HitTestTarget {
|
||||
/// the approximate bounding box of the clip rect that would be
|
||||
/// applied to the given child during the paint phase, if any.
|
||||
///
|
||||
/// Returns null if the child would not be clipped.
|
||||
/// Returns `null` if the child would not be clipped.
|
||||
///
|
||||
/// This is used in the semantics phase to avoid including children
|
||||
/// that are not physically visible.
|
||||
|
@ -54,7 +54,7 @@ class MojoShell {
|
||||
|
||||
/// Attempts to connect to an application via the Mojo shell.
|
||||
///
|
||||
/// Returns null if [canConnectToOtherApplications] is false.
|
||||
/// Returns `null` if [canConnectToOtherApplications] is false.
|
||||
ApplicationConnection connectToApplication(String url) {
|
||||
if (_shell == null)
|
||||
return null;
|
||||
|
@ -104,7 +104,7 @@ class PageStorage extends StatelessWidget {
|
||||
|
||||
/// The bucket from the closest instance of this class that encloses the given context.
|
||||
///
|
||||
/// Returns null if none exists.
|
||||
/// Returns `null` if none exists.
|
||||
static PageStorageBucket of(BuildContext context) {
|
||||
PageStorage widget = context.ancestorWidgetOfExactType(PageStorage);
|
||||
return widget?.bucket;
|
||||
|
@ -468,7 +468,7 @@ abstract class ModalRoute<T> extends TransitionRoute<T> with LocalHistoryRoute<T
|
||||
|
||||
/// Returns the modal route most closely associated with the given context.
|
||||
///
|
||||
/// Returns null if the given context is not associated with a modal route.
|
||||
/// Returns `null` if the given context is not associated with a modal route.
|
||||
static ModalRoute<dynamic> of(BuildContext context) {
|
||||
_ModalScopeStatus widget = context.inheritFromWidgetOfExactType(_ModalScopeStatus);
|
||||
return widget?.route;
|
||||
|
@ -18,7 +18,7 @@ abstract class ScrollBehavior<T, U> {
|
||||
///
|
||||
/// This function is called when a drag gesture ends.
|
||||
///
|
||||
/// Returns null if the behavior is to do nothing.
|
||||
/// Returns `null` if the behavior is to do nothing.
|
||||
Simulation createScrollSimulation(T position, U velocity) => null;
|
||||
|
||||
/// Returns an animation that ends at the snap offset.
|
||||
@ -26,7 +26,7 @@ abstract class ScrollBehavior<T, U> {
|
||||
/// This function is called when a drag gesture ends and a
|
||||
/// [SnapOffsetCallback] is specified for the scrollable.
|
||||
///
|
||||
/// Returns null if the behavior is to do nothing.
|
||||
/// Returns `null` if the behavior is to do nothing.
|
||||
Simulation createSnapScrollSimulation(T startOffset, T endOffset, U startVelocity, U endVelocity) => null;
|
||||
|
||||
/// Returns the scroll offset to use when the user attempts to scroll
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
import 'dart:async';
|
||||
import 'dart:convert' show JSON, JsonEncoder;
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:file/file.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
@ -26,6 +27,8 @@ class TimelineSummary {
|
||||
|
||||
/// Average amount of time spent per frame in the framework building widgets,
|
||||
/// updating layout, painting and compositing.
|
||||
///
|
||||
/// Returns `null` if no frames were recorded.
|
||||
double computeAverageFrameBuildTimeMillis() {
|
||||
int totalBuildTimeMicros = 0;
|
||||
int frameCount = 0;
|
||||
@ -40,6 +43,24 @@ class TimelineSummary {
|
||||
: null;
|
||||
}
|
||||
|
||||
/// Find amount of time spent in the framework building widgets,
|
||||
/// updating layout, painting and compositing on worst frame.
|
||||
///
|
||||
/// Returns `null` if no frames were recorded.
|
||||
double computeWorstFrameBuildTimeMillis() {
|
||||
int maxBuildTimeMicros = 0;
|
||||
int frameCount = 0;
|
||||
|
||||
for (TimedEvent event in _extractBeginFrameEvents()) {
|
||||
frameCount++;
|
||||
maxBuildTimeMicros = math.max(maxBuildTimeMicros, event.duration.inMicroseconds);
|
||||
}
|
||||
|
||||
return frameCount > 0
|
||||
? maxBuildTimeMicros / 1000
|
||||
: null;
|
||||
}
|
||||
|
||||
/// The total number of frames recorded in the timeline.
|
||||
int countFrames() => _extractBeginFrameEvents().length;
|
||||
|
||||
@ -55,6 +76,7 @@ class TimelineSummary {
|
||||
Map<String, dynamic> get summaryJson {
|
||||
return <String, dynamic> {
|
||||
'average_frame_build_time_millis': computeAverageFrameBuildTimeMillis(),
|
||||
'worst_frame_build_time_millis': computeWorstFrameBuildTimeMillis(),
|
||||
'missed_frame_build_budget_count': computeMissedFrameBuildBudgetCount(),
|
||||
'frame_count': countFrames(),
|
||||
'frame_build_times': _extractBeginFrameEvents()
|
||||
|
@ -58,7 +58,7 @@ void main() {
|
||||
end(1000),
|
||||
begin(2000), end(4000),
|
||||
]).computeAverageFrameBuildTimeMillis(),
|
||||
2
|
||||
2.0
|
||||
);
|
||||
});
|
||||
|
||||
@ -68,7 +68,50 @@ void main() {
|
||||
begin(2000), end(4000),
|
||||
begin(5000),
|
||||
]).computeAverageFrameBuildTimeMillis(),
|
||||
2
|
||||
2.0
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('worst_frame_build_time_millis', () {
|
||||
test('returns null when there is no data', () {
|
||||
expect(summarize([]).computeWorstFrameBuildTimeMillis(), isNull);
|
||||
});
|
||||
|
||||
test('computes worst frame build time in milliseconds', () {
|
||||
expect(
|
||||
summarize([
|
||||
begin(1000), end(2000),
|
||||
begin(3000), end(5000),
|
||||
]).computeWorstFrameBuildTimeMillis(),
|
||||
2.0
|
||||
);
|
||||
expect(
|
||||
summarize([
|
||||
begin(3000), end(5000),
|
||||
begin(1000), end(2000),
|
||||
]).computeWorstFrameBuildTimeMillis(),
|
||||
2.0
|
||||
);
|
||||
});
|
||||
|
||||
test('skips leading "end" events', () {
|
||||
expect(
|
||||
summarize([
|
||||
end(1000),
|
||||
begin(2000), end(4000),
|
||||
]).computeWorstFrameBuildTimeMillis(),
|
||||
2.0
|
||||
);
|
||||
});
|
||||
|
||||
test('skips trailing "begin" events', () {
|
||||
expect(
|
||||
summarize([
|
||||
begin(2000), end(4000),
|
||||
begin(5000),
|
||||
]).computeWorstFrameBuildTimeMillis(),
|
||||
2.0
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -96,6 +139,7 @@ void main() {
|
||||
]).summaryJson,
|
||||
{
|
||||
'average_frame_build_time_millis': 7.0,
|
||||
'worst_frame_build_time_millis': 11.0,
|
||||
'missed_frame_build_budget_count': 2,
|
||||
'frame_count': 3,
|
||||
'frame_build_times': <int>[9000, 1000, 11000],
|
||||
@ -131,6 +175,7 @@ void main() {
|
||||
await fs.file('/temp/test.timeline_summary.json').readAsString();
|
||||
expect(JSON.decode(written), {
|
||||
'average_frame_build_time_millis': 7.0,
|
||||
'worst_frame_build_time_millis': 11.0,
|
||||
'missed_frame_build_budget_count': 2,
|
||||
'frame_count': 3,
|
||||
'frame_build_times': <int>[9000, 1000, 11000],
|
||||
|
Loading…
Reference in New Issue
Block a user