@@ -7,6 +7,7 @@ import 'dart:convert' show json;
7
7
import 'dart:js_interop' ;
8
8
import 'dart:math' as math;
9
9
10
+ import 'package:args/args.dart' ;
10
11
import 'package:web/web.dart' as web;
11
12
12
13
import 'src/web/bench_build_image.dart' ;
@@ -81,9 +82,28 @@ final Map<String, RecorderFactory> benchmarks = <String, RecorderFactory>{
81
82
BenchImageDecoding .benchmarkName: () => BenchImageDecoding (),
82
83
};
83
84
84
- final LocalBenchmarkServerClient _client = LocalBenchmarkServerClient ();
85
+ late final LocalBenchmarkServerClient _client;
86
+
87
+ Future <void > main (List <String > args) async {
88
+ final ArgParser parser =
89
+ ArgParser ()..addOption (
90
+ 'port' ,
91
+ abbr: 'p' ,
92
+ help:
93
+ 'The port of the local benchmark server used that implements the '
94
+ 'API required for orchestrating macrobenchmarks.' ,
95
+ );
96
+ final ArgResults argResults = parser.parse (args);
97
+ Uri serverOrigin;
98
+ if (argResults.wasParsed ('port' )) {
99
+ final int port = int .parse (argResults['port' ] as String );
100
+ serverOrigin = Uri .http ('localhost:$port ' );
101
+ } else {
102
+ serverOrigin = Uri .base ;
103
+ }
104
+
105
+ _client = LocalBenchmarkServerClient (serverOrigin);
85
106
86
- Future <void > main () async {
87
107
// Check if the benchmark server wants us to run a specific benchmark.
88
108
final String nextBenchmark = await _client.requestNextBenchmark ();
89
109
@@ -96,6 +116,14 @@ Future<void> main() async {
96
116
web.window.location.reload ();
97
117
}
98
118
119
+ /// Shared entrypoint used for DDC, which runs the macrobenchmarks server on a
120
+ /// separate port.
121
+ // TODO(markzipan): Use `main` in `'web_benchmarks.dart` when Flutter Web supports the `--dart-entrypoint-args` flag.
122
+ // ignore: unreachable_from_main
123
+ Future <void > sharedMain (List <String > args) {
124
+ return main (args);
125
+ }
126
+
99
127
Future <void > _runBenchmark (String benchmarkName) async {
100
128
final RecorderFactory ? recorderFactory = benchmarks[benchmarkName];
101
129
@@ -310,23 +338,36 @@ class TimeseriesVisualization {
310
338
/// implement a manual fallback. This allows debugging benchmarks using plain
311
339
/// `flutter run` .
312
340
class LocalBenchmarkServerClient {
341
+ LocalBenchmarkServerClient (this .serverOrigin);
342
+
313
343
/// This value is returned by [requestNextBenchmark] .
314
344
static const String kManualFallback = '__manual_fallback__' ;
315
345
346
+ /// The origin (e.g., http://localhost:1234) of the benchmark server that
347
+ /// hosts the macrobenchmarking API.
348
+ final Uri serverOrigin;
349
+
316
350
/// Whether we fell back to manual mode.
317
351
///
318
352
/// This happens when you run benchmarks using plain `flutter run` rather than
319
353
/// devicelab test harness. The test harness spins up a special server that
320
354
/// provides API for automatically picking the next benchmark to run.
321
355
bool isInManualMode = false ;
322
356
357
+ Map <String , String > get headers => < String , String > {
358
+ 'Access-Control-Allow-Headers' : 'Origin, Content-Type, Accept' ,
359
+ 'Access-Control-Allow-Methods' : 'Post' ,
360
+ 'Access-Control-Allow-Origin' : serverOrigin.path,
361
+ };
362
+
323
363
/// Asks the local server for the name of the next benchmark to run.
324
364
///
325
365
/// Returns [kManualFallback] if local server is not available (uses 404 as a
326
366
/// signal).
327
367
Future <String > requestNextBenchmark () async {
328
368
final web.XMLHttpRequest request = await _requestXhr (
329
- '/next-benchmark' ,
369
+ serverOrigin.resolve ('next-benchmark' ),
370
+ requestHeaders: headers,
330
371
method: 'POST' ,
331
372
mimeType: 'application/json' ,
332
373
sendData: json.encode (benchmarks.keys.toList ()),
@@ -358,7 +399,8 @@ class LocalBenchmarkServerClient {
358
399
Future <void > startPerformanceTracing (String benchmarkName) async {
359
400
_checkNotManualMode ();
360
401
await _requestXhr (
361
- '/start-performance-tracing?label=$benchmarkName ' ,
402
+ serverOrigin.resolve ('start-performance-tracing?label=$benchmarkName ' ),
403
+ requestHeaders: headers,
362
404
method: 'POST' ,
363
405
mimeType: 'application/json' ,
364
406
);
@@ -367,15 +409,21 @@ class LocalBenchmarkServerClient {
367
409
/// Stops the performance tracing session started by [startPerformanceTracing] .
368
410
Future <void > stopPerformanceTracing () async {
369
411
_checkNotManualMode ();
370
- await _requestXhr ('/stop-performance-tracing' , method: 'POST' , mimeType: 'application/json' );
412
+ await _requestXhr (
413
+ serverOrigin.resolve ('stop-performance-tracing' ),
414
+ requestHeaders: headers,
415
+ method: 'POST' ,
416
+ mimeType: 'application/json' ,
417
+ );
371
418
}
372
419
373
420
/// Sends the profile data collected by the benchmark to the local benchmark
374
421
/// server.
375
422
Future <void > sendProfileData (Profile profile) async {
376
423
_checkNotManualMode ();
377
424
final web.XMLHttpRequest request = await _requestXhr (
378
- '/profile-data' ,
425
+ serverOrigin.resolve ('profile-data' ),
426
+ requestHeaders: headers,
379
427
method: 'POST' ,
380
428
mimeType: 'application/json' ,
381
429
sendData: json.encode (profile.toJson ()),
@@ -394,7 +442,8 @@ class LocalBenchmarkServerClient {
394
442
Future <void > reportError (dynamic error, StackTrace stackTrace) async {
395
443
_checkNotManualMode ();
396
444
await _requestXhr (
397
- '/on-error' ,
445
+ serverOrigin.resolve ('on-error' ),
446
+ requestHeaders: headers,
398
447
method: 'POST' ,
399
448
mimeType: 'application/json' ,
400
449
sendData: json.encode (< String , dynamic > {'error' : '$error ' , 'stackTrace' : '$stackTrace ' }),
@@ -405,7 +454,8 @@ class LocalBenchmarkServerClient {
405
454
Future <void > printToConsole (String report) async {
406
455
_checkNotManualMode ();
407
456
await _requestXhr (
408
- '/print-to-console' ,
457
+ serverOrigin.resolve ('print-to-console' ),
458
+ requestHeaders: headers,
409
459
method: 'POST' ,
410
460
mimeType: 'text/plain' ,
411
461
sendData: report,
@@ -415,7 +465,7 @@ class LocalBenchmarkServerClient {
415
465
/// This is the same as calling [html.HttpRequest.request] but it doesn't
416
466
/// crash on 404, which we use to detect `flutter run` .
417
467
Future <web.XMLHttpRequest > _requestXhr (
418
- String url, {
468
+ Uri url, {
419
469
String ? method,
420
470
bool ? withCredentials,
421
471
String ? responseType,
@@ -427,7 +477,7 @@ class LocalBenchmarkServerClient {
427
477
final web.XMLHttpRequest xhr = web.XMLHttpRequest ();
428
478
429
479
method ?? = 'GET' ;
430
- xhr.open (method, url, true );
480
+ xhr.open (method, '$ url ' , true );
431
481
432
482
if (withCredentials != null ) {
433
483
xhr.withCredentials = withCredentials;
0 commit comments