mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
Add Web Benchmarks for Flutter Gallery (Flutter Side) — 1/4 (#57576)
This commit is contained in:
parent
5d61bff294
commit
02f8e02880
@ -18,8 +18,10 @@ web_shard_template: &WEB_SHARD_TEMPLATE
|
|||||||
linux_shard_template: &LINUX_SHARD_TEMPLATE
|
linux_shard_template: &LINUX_SHARD_TEMPLATE
|
||||||
environment:
|
environment:
|
||||||
# Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
|
# Some of the host-only devicelab tests are pretty involved and need a lot of RAM.
|
||||||
CPU: 2
|
# In June 2020, the CPU and memory were increased so that
|
||||||
MEMORY: 8G
|
# web benchmarks (including gallery benchmarks) can be run successfully on Linux.
|
||||||
|
CPU: 4
|
||||||
|
MEMORY: 16G
|
||||||
script:
|
script:
|
||||||
- dart --enable-asserts ./dev/bots/test.dart
|
- dart --enable-asserts ./dev/bots/test.dart
|
||||||
|
|
||||||
|
@ -0,0 +1,48 @@
|
|||||||
|
// 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/material.dart';
|
||||||
|
|
||||||
|
import 'package:gallery/benchmarks/gallery_automator.dart';
|
||||||
|
|
||||||
|
import 'package:macrobenchmarks/src/web/recorder.dart';
|
||||||
|
|
||||||
|
/// A recorder that measures frame building durations for the Gallery.
|
||||||
|
class GalleryRecorder extends WidgetRecorder {
|
||||||
|
GalleryRecorder({
|
||||||
|
@required this.benchmarkName,
|
||||||
|
this.shouldRunPredicate,
|
||||||
|
this.testScrollsOnly = false,
|
||||||
|
}) : assert(testScrollsOnly || shouldRunPredicate != null),
|
||||||
|
super(name: benchmarkName, useCustomWarmUp: true);
|
||||||
|
|
||||||
|
/// The name of the gallery benchmark to be run.
|
||||||
|
final String benchmarkName;
|
||||||
|
|
||||||
|
/// A function that accepts the name of a demo and returns whether we should
|
||||||
|
/// run this demo in this benchmark.
|
||||||
|
final bool Function(String) shouldRunPredicate;
|
||||||
|
|
||||||
|
/// Whether this benchmark only tests scrolling.
|
||||||
|
final bool testScrollsOnly;
|
||||||
|
|
||||||
|
/// Whether we should continue recording.
|
||||||
|
@override
|
||||||
|
bool shouldContinue() => !_finished || profile.shouldContinue();
|
||||||
|
|
||||||
|
GalleryAutomator _galleryAutomator;
|
||||||
|
bool get _finished => _galleryAutomator?.finished ?? false;
|
||||||
|
|
||||||
|
/// Creates the [GalleryAutomator] widget.
|
||||||
|
@override
|
||||||
|
Widget createWidget() {
|
||||||
|
_galleryAutomator = GalleryAutomator(
|
||||||
|
benchmarkName: benchmarkName,
|
||||||
|
shouldRunPredicate: shouldRunPredicate,
|
||||||
|
testScrollsOnly: testScrollsOnly,
|
||||||
|
stopWarmingUpCallback: profile.stopWarmingUp,
|
||||||
|
);
|
||||||
|
return _galleryAutomator.createWidget();
|
||||||
|
}
|
||||||
|
}
|
@ -235,7 +235,7 @@ abstract class SceneBuilderRecorder extends Recorder {
|
|||||||
|
|
||||||
window.onBeginFrame = (_) {
|
window.onBeginFrame = (_) {
|
||||||
try {
|
try {
|
||||||
startMeasureFrame();
|
startMeasureFrame(profile);
|
||||||
onBeginFrame();
|
onBeginFrame();
|
||||||
} catch (error, stackTrace) {
|
} catch (error, stackTrace) {
|
||||||
profileCompleter.completeError(error, stackTrace);
|
profileCompleter.completeError(error, stackTrace);
|
||||||
@ -333,7 +333,10 @@ abstract class SceneBuilderRecorder extends Recorder {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
abstract class WidgetRecorder extends Recorder implements FrameRecorder {
|
abstract class WidgetRecorder extends Recorder implements FrameRecorder {
|
||||||
WidgetRecorder({@required String name}) : super._(name, true);
|
WidgetRecorder({
|
||||||
|
@required String name,
|
||||||
|
this.useCustomWarmUp = false,
|
||||||
|
}) : super._(name, true);
|
||||||
|
|
||||||
/// Creates a widget to be benchmarked.
|
/// Creates a widget to be benchmarked.
|
||||||
///
|
///
|
||||||
@ -349,12 +352,15 @@ abstract class WidgetRecorder extends Recorder implements FrameRecorder {
|
|||||||
Profile profile;
|
Profile profile;
|
||||||
Completer<void> _runCompleter;
|
Completer<void> _runCompleter;
|
||||||
|
|
||||||
|
/// Whether to delimit warm-up frames in a custom way.
|
||||||
|
final bool useCustomWarmUp;
|
||||||
|
|
||||||
Stopwatch _drawFrameStopwatch;
|
Stopwatch _drawFrameStopwatch;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void frameWillDraw() {
|
void frameWillDraw() {
|
||||||
startMeasureFrame();
|
startMeasureFrame(profile);
|
||||||
_drawFrameStopwatch = Stopwatch()..start();
|
_drawFrameStopwatch = Stopwatch()..start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -380,7 +386,7 @@ abstract class WidgetRecorder extends Recorder implements FrameRecorder {
|
|||||||
@override
|
@override
|
||||||
Future<Profile> run() async {
|
Future<Profile> run() async {
|
||||||
_runCompleter = Completer<void>();
|
_runCompleter = Completer<void>();
|
||||||
final Profile localProfile = profile = Profile(name: name);
|
final Profile localProfile = profile = Profile(name: name, useCustomWarmUp: useCustomWarmUp);
|
||||||
final _RecordingWidgetsBinding binding =
|
final _RecordingWidgetsBinding binding =
|
||||||
_RecordingWidgetsBinding.ensureInitialized();
|
_RecordingWidgetsBinding.ensureInitialized();
|
||||||
final Widget widget = createWidget();
|
final Widget widget = createWidget();
|
||||||
@ -460,7 +466,7 @@ abstract class WidgetBuildRecorder extends Recorder implements FrameRecorder {
|
|||||||
@mustCallSuper
|
@mustCallSuper
|
||||||
void frameWillDraw() {
|
void frameWillDraw() {
|
||||||
if (showWidget) {
|
if (showWidget) {
|
||||||
startMeasureFrame();
|
startMeasureFrame(profile);
|
||||||
_drawFrameStopwatch = Stopwatch()..start();
|
_drawFrameStopwatch = Stopwatch()..start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -538,7 +544,8 @@ class _WidgetBuildRecorderHostState extends State<_WidgetBuildRecorderHost> {
|
|||||||
/// calculations will only apply to the latest [_kMeasuredSampleCount] data
|
/// calculations will only apply to the latest [_kMeasuredSampleCount] data
|
||||||
/// points.
|
/// points.
|
||||||
class Timeseries {
|
class Timeseries {
|
||||||
Timeseries(this.name, this.isReported);
|
Timeseries(this.name, this.isReported, {this.useCustomWarmUp = false})
|
||||||
|
: _warmUpFrameCount = useCustomWarmUp ? 0 : null;
|
||||||
|
|
||||||
/// The label of this timeseries used for debugging and result inspection.
|
/// The label of this timeseries used for debugging and result inspection.
|
||||||
final String name;
|
final String name;
|
||||||
@ -553,6 +560,18 @@ class Timeseries {
|
|||||||
/// but that are too fine-grained to be useful for tracking on the dashboard.
|
/// but that are too fine-grained to be useful for tracking on the dashboard.
|
||||||
final bool isReported;
|
final bool isReported;
|
||||||
|
|
||||||
|
/// Whether to delimit warm-up frames in a custom way.
|
||||||
|
final bool useCustomWarmUp;
|
||||||
|
|
||||||
|
/// The number of frames ignored as warm-up frames, used only
|
||||||
|
/// when [useCustomWarmUp] is true.
|
||||||
|
int _warmUpFrameCount;
|
||||||
|
|
||||||
|
/// The number of frames ignored as warm-up frames.
|
||||||
|
int get warmUpFrameCount => useCustomWarmUp
|
||||||
|
? _warmUpFrameCount
|
||||||
|
: count - _kMeasuredSampleCount;
|
||||||
|
|
||||||
/// List of all the values that have been recorded.
|
/// List of all the values that have been recorded.
|
||||||
///
|
///
|
||||||
/// This list has no limit.
|
/// This list has no limit.
|
||||||
@ -566,11 +585,15 @@ class Timeseries {
|
|||||||
///
|
///
|
||||||
/// See [TimeseriesStats] for more details.
|
/// See [TimeseriesStats] for more details.
|
||||||
TimeseriesStats computeStats() {
|
TimeseriesStats computeStats() {
|
||||||
|
final int finalWarmUpFrameCount = warmUpFrameCount;
|
||||||
|
|
||||||
|
assert(finalWarmUpFrameCount >= 0 && finalWarmUpFrameCount < count);
|
||||||
|
|
||||||
// The first few values we simply discard and never look at. They're from the warm-up phase.
|
// The first few values we simply discard and never look at. They're from the warm-up phase.
|
||||||
final List<double> warmUpValues = _allValues.sublist(0, _allValues.length - _kMeasuredSampleCount);
|
final List<double> warmUpValues = _allValues.sublist(0, finalWarmUpFrameCount);
|
||||||
|
|
||||||
// Values we analyze.
|
// Values we analyze.
|
||||||
final List<double> candidateValues = _allValues.sublist(_allValues.length - _kMeasuredSampleCount);
|
final List<double> candidateValues = _allValues.sublist(finalWarmUpFrameCount);
|
||||||
|
|
||||||
// The average that includes outliers.
|
// The average that includes outliers.
|
||||||
final double dirtyAverage = _computeAverage(name, candidateValues);
|
final double dirtyAverage = _computeAverage(name, candidateValues);
|
||||||
@ -628,13 +651,16 @@ class Timeseries {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a value to this timeseries.
|
/// Adds a value to this timeseries.
|
||||||
void add(double value) {
|
void add(double value, {@required bool isWarmUpValue}) {
|
||||||
if (value < 0.0) {
|
if (value < 0.0) {
|
||||||
throw StateError(
|
throw StateError(
|
||||||
'Timeseries $name: negative metric values are not supported. Got: $value',
|
'Timeseries $name: negative metric values are not supported. Got: $value',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_allValues.add(value);
|
_allValues.add(value);
|
||||||
|
if (useCustomWarmUp && isWarmUpValue) {
|
||||||
|
_warmUpFrameCount += 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -748,11 +774,36 @@ class AnnotatedSample {
|
|||||||
|
|
||||||
/// Base class for a profile collected from running a benchmark.
|
/// Base class for a profile collected from running a benchmark.
|
||||||
class Profile {
|
class Profile {
|
||||||
Profile({@required this.name}) : assert(name != null);
|
Profile({@required this.name, this.useCustomWarmUp = false})
|
||||||
|
: assert(name != null),
|
||||||
|
_isWarmingUp = useCustomWarmUp;
|
||||||
|
|
||||||
/// The name of the benchmark that produced this profile.
|
/// The name of the benchmark that produced this profile.
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
|
/// Whether to delimit warm-up frames in a custom way.
|
||||||
|
final bool useCustomWarmUp;
|
||||||
|
|
||||||
|
/// Whether we are measuring warm-up frames currently.
|
||||||
|
bool get isWarmingUp => _isWarmingUp;
|
||||||
|
|
||||||
|
bool _isWarmingUp;
|
||||||
|
|
||||||
|
/// Stop the warm-up phase.
|
||||||
|
///
|
||||||
|
/// Call this method only when [useCustomWarmUp] and [isWarmingUp] are both
|
||||||
|
/// true.
|
||||||
|
/// Call this method only once for each profile.
|
||||||
|
void stopWarmingUp() {
|
||||||
|
if (!useCustomWarmUp) {
|
||||||
|
throw Exception('`stopWarmingUp` should be used only when `useCustomWarmUp` is true.');
|
||||||
|
} else if (!_isWarmingUp) {
|
||||||
|
throw Exception('Warm-up already stopped.');
|
||||||
|
} else {
|
||||||
|
_isWarmingUp = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// This data will be used to display cards in the Flutter Dashboard.
|
/// This data will be used to display cards in the Flutter Dashboard.
|
||||||
final Map<String, Timeseries> scoreData = <String, Timeseries>{};
|
final Map<String, Timeseries> scoreData = <String, Timeseries>{};
|
||||||
|
|
||||||
@ -773,7 +824,10 @@ class Profile {
|
|||||||
/// Set [reported] to `false` to store the data, but not show it on the
|
/// Set [reported] to `false` to store the data, but not show it on the
|
||||||
/// dashboard UI.
|
/// dashboard UI.
|
||||||
void addDataPoint(String key, Duration duration, { @required bool reported }) {
|
void addDataPoint(String key, Duration duration, { @required bool reported }) {
|
||||||
scoreData.putIfAbsent(key, () => Timeseries(key, reported)).add(duration.inMicroseconds.toDouble());
|
scoreData.putIfAbsent(
|
||||||
|
key,
|
||||||
|
() => Timeseries(key, reported, useCustomWarmUp: useCustomWarmUp),
|
||||||
|
).add(duration.inMicroseconds.toDouble(), isWarmUpValue: isWarmingUp);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decides whether the data collected so far is sufficient to stop, or
|
/// Decides whether the data collected so far is sufficient to stop, or
|
||||||
@ -1007,6 +1061,20 @@ class _RecordingWidgetsBinding extends BindingBase
|
|||||||
|
|
||||||
int _currentFrameNumber = 1;
|
int _currentFrameNumber = 1;
|
||||||
|
|
||||||
|
/// If [_calledStartMeasureFrame] is true, we have called [startMeasureFrame]
|
||||||
|
/// but have not its pairing [endMeasureFrame] yet.
|
||||||
|
///
|
||||||
|
/// This flag ensures that [startMeasureFrame] and [endMeasureFrame] are always
|
||||||
|
/// called in pairs, with [startMeasureFrame] followed by [endMeasureFrame].
|
||||||
|
bool _calledStartMeasureFrame = false;
|
||||||
|
|
||||||
|
/// Whether we are recording a measured frame.
|
||||||
|
///
|
||||||
|
/// This flag ensures that we always stop measuring a frame if we
|
||||||
|
/// have started one. Because we want to skip warm-up frames, this flag
|
||||||
|
/// is necessary.
|
||||||
|
bool _isMeasuringFrame = false;
|
||||||
|
|
||||||
/// Adds a marker indication the beginning of frame rendering.
|
/// Adds a marker indication the beginning of frame rendering.
|
||||||
///
|
///
|
||||||
/// This adds an event to the performance trace used to find measured frames in
|
/// This adds an event to the performance trace used to find measured frames in
|
||||||
@ -1014,22 +1082,53 @@ int _currentFrameNumber = 1;
|
|||||||
/// benchmarks are only interested in a subset of frames. For example,
|
/// benchmarks are only interested in a subset of frames. For example,
|
||||||
/// [WidgetBuildRecorder] only measures frames that build widgets, and ignores
|
/// [WidgetBuildRecorder] only measures frames that build widgets, and ignores
|
||||||
/// frames that clear the screen.
|
/// frames that clear the screen.
|
||||||
void startMeasureFrame() {
|
///
|
||||||
html.window.performance.mark('measured_frame_start#$_currentFrameNumber');
|
/// Warm-up frames are not measured. If [profile.isWarmingUp] is true,
|
||||||
|
/// this function does nothing.
|
||||||
|
void startMeasureFrame(Profile profile) {
|
||||||
|
if (_calledStartMeasureFrame) {
|
||||||
|
throw Exception('`startMeasureFrame` called twice in a row.');
|
||||||
|
}
|
||||||
|
|
||||||
|
_calledStartMeasureFrame = true;
|
||||||
|
|
||||||
|
if (!profile.isWarmingUp) {
|
||||||
|
// Tell the browser to mark the beginning of the frame.
|
||||||
|
html.window.performance.mark('measured_frame_start#$_currentFrameNumber');
|
||||||
|
|
||||||
|
_isMeasuringFrame = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signals the end of a measured frame.
|
/// Signals the end of a measured frame.
|
||||||
///
|
///
|
||||||
/// See [startMeasureFrame] for details on what this instrumentation is used
|
/// See [startMeasureFrame] for details on what this instrumentation is used
|
||||||
/// for.
|
/// for.
|
||||||
|
///
|
||||||
|
/// Warm-up frames are not measured. If [profile.isWarmingUp] was true
|
||||||
|
/// when the corresponding [startMeasureFrame] was called,
|
||||||
|
/// this function does nothing.
|
||||||
void endMeasureFrame() {
|
void endMeasureFrame() {
|
||||||
html.window.performance.mark('measured_frame_end#$_currentFrameNumber');
|
if (!_calledStartMeasureFrame) {
|
||||||
html.window.performance.measure(
|
throw Exception('`startMeasureFrame` has not been called before calling `endMeasureFrame`');
|
||||||
'measured_frame',
|
}
|
||||||
'measured_frame_start#$_currentFrameNumber',
|
|
||||||
'measured_frame_end#$_currentFrameNumber',
|
_calledStartMeasureFrame = false;
|
||||||
);
|
|
||||||
_currentFrameNumber += 1;
|
if (_isMeasuringFrame) {
|
||||||
|
// Tell the browser to mark the end of the frame, and measure the duration.
|
||||||
|
html.window.performance.mark('measured_frame_end#$_currentFrameNumber');
|
||||||
|
html.window.performance.measure(
|
||||||
|
'measured_frame',
|
||||||
|
'measured_frame_start#$_currentFrameNumber',
|
||||||
|
'measured_frame_end#$_currentFrameNumber',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Increment the current frame number.
|
||||||
|
_currentFrameNumber += 1;
|
||||||
|
|
||||||
|
_isMeasuringFrame = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A function that receives a benchmark value from the framework.
|
/// A function that receives a benchmark value from the framework.
|
||||||
|
@ -10,6 +10,8 @@ import 'dart:math' as math;
|
|||||||
import 'package:macrobenchmarks/src/web/bench_text_layout.dart';
|
import 'package:macrobenchmarks/src/web/bench_text_layout.dart';
|
||||||
import 'package:macrobenchmarks/src/web/bench_text_out_of_picture_bounds.dart';
|
import 'package:macrobenchmarks/src/web/bench_text_out_of_picture_bounds.dart';
|
||||||
|
|
||||||
|
import 'package:gallery/benchmarks/gallery_automator.dart' show DemoType, typeOfDemo;
|
||||||
|
|
||||||
import 'src/web/bench_build_material_checkbox.dart';
|
import 'src/web/bench_build_material_checkbox.dart';
|
||||||
import 'src/web/bench_card_infinite_scroll.dart';
|
import 'src/web/bench_card_infinite_scroll.dart';
|
||||||
import 'src/web/bench_child_layers.dart';
|
import 'src/web/bench_child_layers.dart';
|
||||||
@ -22,12 +24,15 @@ import 'src/web/bench_paths.dart';
|
|||||||
import 'src/web/bench_picture_recording.dart';
|
import 'src/web/bench_picture_recording.dart';
|
||||||
import 'src/web/bench_simple_lazy_text_scroll.dart';
|
import 'src/web/bench_simple_lazy_text_scroll.dart';
|
||||||
import 'src/web/bench_text_out_of_picture_bounds.dart';
|
import 'src/web/bench_text_out_of_picture_bounds.dart';
|
||||||
|
import 'src/web/gallery/gallery_recorder.dart';
|
||||||
import 'src/web/recorder.dart';
|
import 'src/web/recorder.dart';
|
||||||
|
|
||||||
typedef RecorderFactory = Recorder Function();
|
typedef RecorderFactory = Recorder Function();
|
||||||
|
|
||||||
const bool isCanvasKit = bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false);
|
const bool isCanvasKit = bool.fromEnvironment('FLUTTER_WEB_USE_SKIA', defaultValue: false);
|
||||||
|
|
||||||
|
const String _galleryBenchmarkPrefix = 'gallery_v2';
|
||||||
|
|
||||||
/// List of all benchmarks that run in the devicelab.
|
/// List of all benchmarks that run in the devicelab.
|
||||||
///
|
///
|
||||||
/// When adding a new benchmark, add it to this map. Make sure that the name
|
/// When adding a new benchmark, add it to this map. Make sure that the name
|
||||||
@ -57,7 +62,16 @@ final Map<String, RecorderFactory> benchmarks = <String, RecorderFactory>{
|
|||||||
BenchTextCachedLayout.canvasBenchmarkName: () => BenchTextCachedLayout(useCanvas: true),
|
BenchTextCachedLayout.canvasBenchmarkName: () => BenchTextCachedLayout(useCanvas: true),
|
||||||
BenchBuildColorsGrid.domBenchmarkName: () => BenchBuildColorsGrid.dom(),
|
BenchBuildColorsGrid.domBenchmarkName: () => BenchBuildColorsGrid.dom(),
|
||||||
BenchBuildColorsGrid.canvasBenchmarkName: () => BenchBuildColorsGrid.canvas(),
|
BenchBuildColorsGrid.canvasBenchmarkName: () => BenchBuildColorsGrid.canvas(),
|
||||||
}
|
|
||||||
|
// The following benchmark is for the Flutter Gallery.
|
||||||
|
// This benchmark is failing when run with CanvasKit, so we skip it
|
||||||
|
// for now.
|
||||||
|
// TODO(yjbanov): https://github.com/flutter/flutter/issues/59082
|
||||||
|
'${_galleryBenchmarkPrefix}_studies_perf': () => GalleryRecorder(
|
||||||
|
benchmarkName: '${_galleryBenchmarkPrefix}_studies_perf',
|
||||||
|
shouldRunPredicate: (String demo) => typeOfDemo(demo) == DemoType.study,
|
||||||
|
),
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
final LocalBenchmarkServerClient _client = LocalBenchmarkServerClient();
|
final LocalBenchmarkServerClient _client = LocalBenchmarkServerClient();
|
||||||
@ -83,29 +97,48 @@ Future<void> _runBenchmark(String benchmarkName) async {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
await runZoned<Future<void>>(
|
||||||
final Recorder recorder = recorderFactory();
|
() async {
|
||||||
final Runner runner = recorder.isTracingEnabled && !_client.isInManualMode
|
final Recorder recorder = recorderFactory();
|
||||||
? Runner(
|
final Runner runner = recorder.isTracingEnabled && !_client.isInManualMode
|
||||||
recorder: recorder,
|
? Runner(
|
||||||
setUpAllDidRun: () => _client.startPerformanceTracing(benchmarkName),
|
recorder: recorder,
|
||||||
tearDownAllWillRun: _client.stopPerformanceTracing,
|
setUpAllDidRun: () => _client.startPerformanceTracing(benchmarkName),
|
||||||
)
|
tearDownAllWillRun: _client.stopPerformanceTracing,
|
||||||
: Runner(recorder: recorder);
|
)
|
||||||
|
: Runner(recorder: recorder);
|
||||||
|
|
||||||
final Profile profile = await runner.run();
|
final Profile profile = await runner.run();
|
||||||
if (!_client.isInManualMode) {
|
if (!_client.isInManualMode) {
|
||||||
await _client.sendProfileData(profile);
|
await _client.sendProfileData(profile);
|
||||||
} else {
|
} else {
|
||||||
_printResultsToScreen(profile);
|
_printResultsToScreen(profile);
|
||||||
print(profile);
|
print(profile);
|
||||||
}
|
}
|
||||||
} catch (error, stackTrace) {
|
},
|
||||||
if (_client.isInManualMode) {
|
zoneSpecification: ZoneSpecification(
|
||||||
rethrow;
|
print: (Zone self, ZoneDelegate parent, Zone zone, String line) async {
|
||||||
}
|
if (_client.isInManualMode) {
|
||||||
await _client.reportError(error, stackTrace);
|
parent.print(zone, '[$benchmarkName] $line');
|
||||||
}
|
} else {
|
||||||
|
await _client.printToConsole(line);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleUncaughtError: (
|
||||||
|
Zone self,
|
||||||
|
ZoneDelegate parent,
|
||||||
|
Zone zone, Object error,
|
||||||
|
StackTrace stackTrace,
|
||||||
|
) async {
|
||||||
|
if (_client.isInManualMode) {
|
||||||
|
parent.print(zone, '[$benchmarkName] $error, $stackTrace');
|
||||||
|
parent.handleUncaughtError(zone, error, stackTrace);
|
||||||
|
} else {
|
||||||
|
await _client.reportError(error, stackTrace);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _fallbackToManual(String error) {
|
void _fallbackToManual(String error) {
|
||||||
@ -354,6 +387,17 @@ class LocalBenchmarkServerClient {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reports a message about the demo to the benchmark server.
|
||||||
|
Future<void> printToConsole(String report) async {
|
||||||
|
_checkNotManualMode();
|
||||||
|
await html.HttpRequest.request(
|
||||||
|
'/print-to-console',
|
||||||
|
method: 'POST',
|
||||||
|
mimeType: 'text/plain',
|
||||||
|
sendData: report,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
/// This is the same as calling [html.HttpRequest.request] but it doesn't
|
/// This is the same as calling [html.HttpRequest.request] but it doesn't
|
||||||
/// crash on 404, which we use to detect `flutter run`.
|
/// crash on 404, which we use to detect `flutter run`.
|
||||||
Future<html.HttpRequest> _requestXhr(
|
Future<html.HttpRequest> _requestXhr(
|
||||||
|
@ -17,6 +17,12 @@ dependencies:
|
|||||||
# flutter update-packages --force-upgrade
|
# flutter update-packages --force-upgrade
|
||||||
flutter_gallery_assets: 0.2.1
|
flutter_gallery_assets: 0.2.1
|
||||||
|
|
||||||
|
# This is needed for web_benchmarks.
|
||||||
|
gallery:
|
||||||
|
git:
|
||||||
|
url: https://github.com/flutter/gallery.git
|
||||||
|
ref: 0c5ec2f285c1ec30b2ed15194bc8de755654a590
|
||||||
|
|
||||||
archive: 2.0.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
archive: 2.0.13 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
args: 1.6.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
args: 1.6.0 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
async: 2.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
async: 2.4.1 # THIS LINE IS AUTOGENERATED - TO UPDATE USE "flutter update-packages --force-upgrade"
|
||||||
@ -87,8 +93,173 @@ dev_dependencies:
|
|||||||
flutter:
|
flutter:
|
||||||
uses-material-design: true
|
uses-material-design: true
|
||||||
assets:
|
assets:
|
||||||
- packages/flutter_gallery_assets/food/butternut_squash_soup.png
|
- packages/flutter_gallery_assets/food/butternut_squash_soup.png
|
||||||
- packages/flutter_gallery_assets/food/cherry_pie.png
|
- packages/flutter_gallery_assets/food/cherry_pie.png
|
||||||
- assets/999x1000.png
|
- assets/999x1000.png
|
||||||
|
|
||||||
|
# The following assets are required for running Flutter Gallery benchmarks.
|
||||||
|
- packages/flutter_gallery_assets/assets/icons/settings/settings_light.flr
|
||||||
|
- packages/flutter_gallery_assets/assets/icons/settings/settings_dark.flr
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/shrine_card_dark.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/starter_card.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/starter_card_dark.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/fortnightly_card_dark.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/rally_card_dark.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/fortnightly_card.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/crane_card.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/shrine_card.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/crane_card_dark.png
|
||||||
|
- packages/flutter_gallery_assets/assets/studies/rally_card.png
|
||||||
|
- packages/flutter_gallery_assets/assets/logo/flutter_logo.png
|
||||||
|
- packages/flutter_gallery_assets/assets/logo/flutter_logo_color.png
|
||||||
|
- packages/flutter_gallery_assets/assets/icons/cupertino/cupertino.png
|
||||||
|
- packages/flutter_gallery_assets/assets/icons/material/material.png
|
||||||
|
- packages/flutter_gallery_assets/assets/icons/reference/reference.png
|
||||||
|
- packages/flutter_gallery_assets/assets/demos/bottom_navigation_background.png
|
||||||
|
- packages/flutter_gallery_assets/fonts/GalleryIcons.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Merriweather-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Eczar-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Montserrat-Medium.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Rubik-Bold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Merriweather-Light.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/RobotoCondensed-Bold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Medium.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Raleway-SemiBold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/RobotoMono-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-ExtraBold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-Bold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Oswald-SemiBold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Oswald-Medium.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-SemiBold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Montserrat-Bold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Merriweather-BoldItalic.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Raleway-Light.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Rubik-Medium.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Montserrat-SemiBold.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/RobotoCondensed-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/LibreFranklin-Medium.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Montserrat-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Rubik-Regular.ttf
|
||||||
|
- packages/flutter_gallery_assets/fonts/google_fonts/Eczar-SemiBold.ttf
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_1.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_2.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_3.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_4.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_5.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_6.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_7.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_8.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_9.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/eat_10.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_0.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_1.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_2.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_3.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_4.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_5.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_6.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_7.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_8.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_9.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_10.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_11.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_12.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/fly_13.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_0.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_1.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_2.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_3.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_4.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_5.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_6.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_7.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_8.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_9.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_10.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/destinations/sleep_11.jpg
|
||||||
|
- packages/flutter_gallery_assets/crane/logo/logo.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_army.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_bees.jpg
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_chart.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_fabrics.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_feminists.jpg
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_gas.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_healthcare.jpg
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_stocks.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_title.png
|
||||||
|
- packages/flutter_gallery_assets/fortnightly/fortnightly_war.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_chennai_flower_market.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_thanjavur_market.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_tanjore_bronze_works.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_tanjore_market_merchant.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_tanjore_thanjavur_temple.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_pondicherry_salt_farm.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_chennai_highway.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_chettinad_silk_maker.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_tanjore_thanjavur_temple_carvings.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_chettinad_produce.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_tanjore_market_technology.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_pondicherry_beach.png
|
||||||
|
- packages/flutter_gallery_assets/places/india_pondicherry_fisherman.png
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_1.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_2.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_3.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_4.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_5.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_6.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_7.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_8.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_9.gif
|
||||||
|
- packages/flutter_gallery_assets/splash_effects/splash_effect_10.gif
|
||||||
|
- packages/rally_assets/logo.png
|
||||||
|
- packages/rally_assets/thumb.png
|
||||||
|
- packages/shrine_images/diamond.png
|
||||||
|
- packages/shrine_images/slanted_menu.png
|
||||||
|
- packages/shrine_images/0-0.jpg
|
||||||
|
- packages/shrine_images/1-0.jpg
|
||||||
|
- packages/shrine_images/2-0.jpg
|
||||||
|
- packages/shrine_images/3-0.jpg
|
||||||
|
- packages/shrine_images/4-0.jpg
|
||||||
|
- packages/shrine_images/5-0.jpg
|
||||||
|
- packages/shrine_images/6-0.jpg
|
||||||
|
- packages/shrine_images/7-0.jpg
|
||||||
|
- packages/shrine_images/8-0.jpg
|
||||||
|
- packages/shrine_images/9-0.jpg
|
||||||
|
- packages/shrine_images/10-0.jpg
|
||||||
|
- packages/shrine_images/11-0.jpg
|
||||||
|
- packages/shrine_images/12-0.jpg
|
||||||
|
- packages/shrine_images/13-0.jpg
|
||||||
|
- packages/shrine_images/14-0.jpg
|
||||||
|
- packages/shrine_images/15-0.jpg
|
||||||
|
- packages/shrine_images/16-0.jpg
|
||||||
|
- packages/shrine_images/17-0.jpg
|
||||||
|
- packages/shrine_images/18-0.jpg
|
||||||
|
- packages/shrine_images/19-0.jpg
|
||||||
|
- packages/shrine_images/20-0.jpg
|
||||||
|
- packages/shrine_images/21-0.jpg
|
||||||
|
- packages/shrine_images/22-0.jpg
|
||||||
|
- packages/shrine_images/23-0.jpg
|
||||||
|
- packages/shrine_images/24-0.jpg
|
||||||
|
- packages/shrine_images/25-0.jpg
|
||||||
|
- packages/shrine_images/26-0.jpg
|
||||||
|
- packages/shrine_images/27-0.jpg
|
||||||
|
- packages/shrine_images/28-0.jpg
|
||||||
|
- packages/shrine_images/29-0.jpg
|
||||||
|
- packages/shrine_images/30-0.jpg
|
||||||
|
- packages/shrine_images/31-0.jpg
|
||||||
|
- packages/shrine_images/32-0.jpg
|
||||||
|
- packages/shrine_images/33-0.jpg
|
||||||
|
- packages/shrine_images/34-0.jpg
|
||||||
|
- packages/shrine_images/35-0.jpg
|
||||||
|
- packages/shrine_images/36-0.jpg
|
||||||
|
- packages/shrine_images/37-0.jpg
|
||||||
|
|
||||||
|
# The following font is required for running Flutter Gallery benchmarks.
|
||||||
|
fonts:
|
||||||
|
- family: GalleryIcons
|
||||||
|
fonts:
|
||||||
|
- asset: packages/flutter_gallery_assets/fonts/GalleryIcons.ttf
|
||||||
|
|
||||||
# PUBSPEC CHECKSUM: 8ced
|
# PUBSPEC CHECKSUM: 8ced
|
||||||
|
@ -99,6 +99,13 @@ Future<TaskResult> runWebBenchmark({ @required bool useCanvasKit }) async {
|
|||||||
profileData.complete(collectedProfiles);
|
profileData.complete(collectedProfiles);
|
||||||
return Response.notFound('Finished running benchmarks.');
|
return Response.notFound('Finished running benchmarks.');
|
||||||
}
|
}
|
||||||
|
} else if (request.requestedUri.path.endsWith('/print-to-console')) {
|
||||||
|
// A passthrough used by
|
||||||
|
// `dev/benchmarks/macrobenchmarks/lib/web_benchmarks.dart`
|
||||||
|
// to print information.
|
||||||
|
final String message = await request.readAsString();
|
||||||
|
print('[Gallery] $message');
|
||||||
|
return Response.ok('Reported.');
|
||||||
} else {
|
} else {
|
||||||
return Response.notFound(
|
return Response.notFound(
|
||||||
'This request is not handled by the profile-data handler.');
|
'This request is not handled by the profile-data handler.');
|
||||||
|
Loading…
Reference in New Issue
Block a user