4
4
5
5
import 'dart:async' ;
6
6
import 'dart:io' ;
7
- import 'dart:math' as math;
8
7
9
8
import 'package:path/path.dart' as path;
10
9
11
10
import '../framework/framework.dart' ;
12
11
import '../framework/utils.dart' ;
13
12
14
- /// Run each benchmark this many times and compute average.
13
+ /// Run each benchmark this many times and compute average, min, max.
14
+ ///
15
+ /// This must be small enough that we can do all the work in 15 minutes, the
16
+ /// devicelab deadline. Since there's four different analysis tasks, on average,
17
+ /// each can have 4 minutes. The tasks currently average a little more than a
18
+ /// minute, so that allows three runs per task.
15
19
const int _kRunsPerBenchmark = 3 ;
16
20
17
- /// Runs a benchmark once and reports the result as a lower-is-better numeric
18
- /// value.
19
- typedef Future <double > _Benchmark ();
20
-
21
21
/// Path to the generated "mega gallery" app.
22
22
Directory get _megaGalleryDirectory => dir (path.join (Directory .systemTemp.path, 'mega_gallery' ));
23
23
@@ -28,76 +28,101 @@ Future<TaskResult> analyzerBenchmarkTask() async {
28
28
await dart (< String > ['dev/tools/mega_gallery.dart' , '--out=${_megaGalleryDirectory .path }' ]);
29
29
});
30
30
31
- final Map <String , dynamic > data = < String , dynamic > {
32
- 'flutter_repo_batch' : await _run (new _FlutterRepoBenchmark ()),
33
- 'flutter_repo_watch' : await _run (new _FlutterRepoBenchmark (watch: true )),
34
- 'mega_gallery_batch' : await _run (new _MegaGalleryBenchmark ()),
35
- 'mega_gallery_watch' : await _run (new _MegaGalleryBenchmark (watch: true )),
36
- };
31
+ final Map <String , dynamic > data = < String , dynamic > {};
32
+ data.addAll ((await _run (new _FlutterRepoBenchmark ())).asMap ('flutter_repo' , 'batch' ));
33
+ data.addAll ((await _run (new _FlutterRepoBenchmark (watch: true ))).asMap ('flutter_repo' , 'watch' ));
34
+ data.addAll ((await _run (new _MegaGalleryBenchmark ())).asMap ('mega_gallery' , 'batch' ));
35
+ data.addAll ((await _run (new _MegaGalleryBenchmark (watch: true ))).asMap ('mega_gallery' , 'watch' ));
37
36
38
37
return new TaskResult .success (data, benchmarkScoreKeys: data.keys.toList ());
39
38
}
40
39
41
- /// Times how long it takes to analyze the Flutter repository.
42
- class _FlutterRepoBenchmark {
43
- _FlutterRepoBenchmark ({ this .watch = false });
40
+ class _BenchmarkResult {
41
+ const _BenchmarkResult (this .mean, this .min, this .max);
44
42
45
- final bool watch;
43
+ final double mean; // seconds
46
44
47
- Future <double > call () async {
48
- section ('Analyze Flutter repo ${watch ? 'with watcher' : '' }' );
49
- final Stopwatch stopwatch = new Stopwatch ();
50
- await inDirectory (flutterDirectory, () async {
51
- final List <String > options = < String > [
52
- '--flutter-repo' ,
53
- '--benchmark' ,
54
- ];
45
+ final double min; // seconds
55
46
56
- if (watch)
57
- options.add ('--watch' );
47
+ final double max; // seconds
58
48
59
- stopwatch.start ();
60
- await flutter ('analyze' , options: options);
61
- stopwatch.stop ();
62
- });
63
- return stopwatch.elapsedMilliseconds / 1000 ;
49
+ Map <String , dynamic > asMap (String benchmark, String mode) {
50
+ return < String , dynamic > {
51
+ '${benchmark }_$mode ' : mean,
52
+ '${benchmark }_${mode }_minimum' : min,
53
+ '${benchmark }_${mode }_maximum' : max,
54
+ };
64
55
}
65
56
}
66
57
67
- /// Times how long it takes to analyze the generated "mega_gallery" app.
68
- class _MegaGalleryBenchmark {
69
- _MegaGalleryBenchmark ({ this .watch = false });
58
+ abstract class _Benchmark {
59
+ _Benchmark ({ this .watch = false });
70
60
71
61
final bool watch;
72
62
73
- Future <double > call () async {
74
- section ('Analyze mega gallery ${watch ? 'with watcher' : '' }' );
75
- final Stopwatch stopwatch = new Stopwatch ();
76
- await inDirectory (_megaGalleryDirectory, () async {
77
- final List <String > options = < String > [
78
- '--benchmark' ,
79
- ];
63
+ String get title;
80
64
81
- if (watch)
82
- options.add ('--watch' );
65
+ Directory get directory;
83
66
67
+ List <String > get options {
68
+ final List <String > result = < String > [ '--benchmark' ];
69
+ if (watch)
70
+ options.add ('--watch' );
71
+ return result;
72
+ }
73
+
74
+ Future <double > execute (int iteration, int targetIterations) async {
75
+ section ('Analyze $title ${watch ? 'with watcher' : '' } - ${iteration + 1 } / $targetIterations ' );
76
+ final Stopwatch stopwatch = new Stopwatch ();
77
+ await inDirectory (directory, () async {
84
78
stopwatch.start ();
85
79
await flutter ('analyze' , options: options);
86
80
stopwatch.stop ();
87
81
});
88
- return stopwatch.elapsedMilliseconds / 1000 ;
82
+ return stopwatch.elapsedMicroseconds / ( 1000.0 * 1000.0 ) ;
89
83
}
90
84
}
91
85
92
- /// Runs a [benchmark] several times and reports the average result.
93
- Future <double > _run (_Benchmark benchmark) async {
94
- double best;
95
- for (int i = 0 ; i < _kRunsPerBenchmark; i++ ) {
86
+ /// Times how long it takes to analyze the Flutter repository.
87
+ class _FlutterRepoBenchmark extends _Benchmark {
88
+ _FlutterRepoBenchmark ({ bool watch = false }) : super (watch: watch);
89
+
90
+ @override
91
+ String get title => 'Flutter repo' ;
92
+
93
+ @override
94
+ Directory get directory => flutterDirectory;
95
+
96
+ @override
97
+ List <String > get options {
98
+ return super .options
99
+ ..add ('--flutter-repo' );
100
+ }
101
+ }
102
+
103
+ /// Times how long it takes to analyze the generated "mega_gallery" app.
104
+ class _MegaGalleryBenchmark extends _Benchmark {
105
+ _MegaGalleryBenchmark ({ bool watch = false }) : super (watch: watch);
106
+
107
+ @override
108
+ String get title => 'mega gallery' ;
109
+
110
+ @override
111
+ Directory get directory => _megaGalleryDirectory;
112
+ }
113
+
114
+ /// Runs `benchmark` several times and reports the results.
115
+ Future <_BenchmarkResult > _run (_Benchmark benchmark) async {
116
+ final List <double > results = < double > [];
117
+ for (int i = 0 ; i < _kRunsPerBenchmark; i += 1 ) {
96
118
// Delete cached analysis results.
97
119
rmTree (dir ('${Platform .environment ['HOME' ]}/.dartServer' ));
98
-
99
- final double result = await benchmark ();
100
- best = math.min (result, best ?? result);
120
+ results.add (await benchmark.execute (i, _kRunsPerBenchmark));
101
121
}
102
- return best;
122
+ results.sort ();
123
+ final double sum = results.fold <double >(
124
+ 0.0 ,
125
+ (double previousValue, double element) => previousValue + element,
126
+ );
127
+ return new _BenchmarkResult (sum / results.length, results.first, results.last);
103
128
}
0 commit comments