Skip to content

Commit 5dfe7e6

Browse files
author
Jonah Williams
authored
[flutter_tools] attempt to stabilize hot restart benchmark the old fashioned way (flutter#67971)
A change which sped up hot restart locally caused many of the devicelab measures to regress. I think this is because we do not measure when the isolate is actually "ready", so starting a reload or restart prematurely can cause time spent doing initialization to be registered as part of the reload operation. A fix for this would be to have the framework include some sort of "initialization complete" event ... but it is not clear what the correct trigger would be. Perhaps after the first frame is successfully registered? (9a3a0dc caused the benchmark regression - possibly since we spend less time syncing files now so we start the restart earlier)
1 parent 46238de commit 5dfe7e6

File tree

2 files changed

+9
-48
lines changed

2 files changed

+9
-48
lines changed

dev/devicelab/lib/tasks/hot_mode_tests.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ TaskFunction createHotModeTest({String deviceIdOverride, Map<String, String> env
2626
final File benchmarkFile = file(path.join(_editedFlutterGalleryDir.path, 'hot_benchmark.json'));
2727
rm(benchmarkFile);
2828
final List<String> options = <String>[
29-
'--hot', '-d', deviceIdOverride, '--benchmark', '--verbose', '--resident', '--output-dill', path.join('build', 'app.dill')
29+
'--hot', '-d', deviceIdOverride, '--benchmark', '--verbose', '--resident', '--output-dill',
3030
];
3131
int hotReloadCount = 0;
3232
Map<String, dynamic> twoReloadsData;

packages/flutter_tools/lib/src/run_hot.dart

Lines changed: 8 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,6 @@ class HotRunner extends ResidentRunner {
237237
if (debuggingOptions.fastStart) {
238238
await restart(
239239
fullRestart: true,
240-
benchmarkMode: !debuggingOptions.startPaused,
241240
reason: 'restart',
242241
silent: true,
243242
);
@@ -246,14 +245,18 @@ class HotRunner extends ResidentRunner {
246245
appStartedCompleter?.complete();
247246

248247
if (benchmarkMode) {
248+
// Wait multiple seconds for the isolate to have fully started.
249+
await Future<void>.delayed(const Duration(seconds: 10));
249250
// We are running in benchmark mode.
250251
globals.printStatus('Running in benchmark mode.');
251252
// Measure time to perform a hot restart.
252253
globals.printStatus('Benchmarking hot restart');
253-
await restart(fullRestart: true, benchmarkMode: true);
254-
// Wait for notifications to finish. attempt to work around
255-
// timing issue caused by sentinel.
256-
await Future<void>.delayed(const Duration(seconds: 1));
254+
await restart(fullRestart: true);
255+
// Wait multiple seconds to stabilize benchmark on slower devicelab hardware.
256+
// Hot restart finishes when the new isolate is started, not when the new isolate
257+
// is ready. This process can actually take multiple seconds.
258+
await Future<void>.delayed(const Duration(seconds: 10));
259+
257260
globals.printStatus('Benchmarking hot reload');
258261
// Measure time to perform a hot reload.
259262
await restart(fullRestart: false);
@@ -462,22 +465,10 @@ class HotRunner extends ResidentRunner {
462465
deviceAssetsDirectoryUri));
463466
}
464467
await Future.wait(futures);
465-
if (benchmarkMode) {
466-
futures.clear();
467-
for (final FlutterDevice device in flutterDevices) {
468-
final List<FlutterView> views = await device.vmService.getFlutterViews();
469-
for (final FlutterView view in views) {
470-
futures.add(device.vmService
471-
.flushUIThreadTasks(uiIsolateId: view.uiIsolate.id));
472-
}
473-
}
474-
await Future.wait(futures);
475-
}
476468
}
477469

478470
Future<OperationResult> _restartFromSources({
479471
String reason,
480-
bool benchmarkMode = false,
481472
}) async {
482473
final Stopwatch restartTimer = Stopwatch()..start();
483474
// TODO(aam): Add generator reset logic once we switch to using incremental
@@ -562,32 +553,6 @@ class HotRunner extends ResidentRunner {
562553
// Send timing analytics.
563554
globals.flutterUsage.sendTiming('hot', 'restart', restartTimer.elapsed);
564555

565-
if (benchmarkMode) {
566-
final List<Future<void>> isolateNotifications = <Future<void>>[];
567-
for (final FlutterDevice device in flutterDevices) {
568-
try {
569-
await device.vmService.streamListen('Isolate');
570-
} on vm_service.RPCError {
571-
// Do nothing, we're already subscribed.
572-
}
573-
isolateNotifications.add(
574-
device.vmService.onIsolateEvent.firstWhere((vm_service.Event event) {
575-
return event.kind == vm_service.EventKind.kIsolateRunnable;
576-
}),
577-
);
578-
}
579-
await Future.wait(isolateNotifications);
580-
final List<Future<void>> futures = <Future<void>>[];
581-
for (final FlutterDevice device in flutterDevices) {
582-
final List<FlutterView> views = await device.vmService.getFlutterViews();
583-
for (final FlutterView view in views) {
584-
futures.add(device.vmService
585-
.flushUIThreadTasks(uiIsolateId: view.uiIsolate.id));
586-
}
587-
}
588-
await Future.wait(futures);
589-
}
590-
591556
// Toggle the main dill name after successfully uploading.
592557
_swap =! _swap;
593558

@@ -626,7 +591,6 @@ class HotRunner extends ResidentRunner {
626591
Future<OperationResult> restart({
627592
bool fullRestart = false,
628593
String reason,
629-
bool benchmarkMode = false,
630594
bool silent = false,
631595
bool pause = false,
632596
}) async {
@@ -658,7 +622,6 @@ class HotRunner extends ResidentRunner {
658622
sdkName: sdkName,
659623
emulator: emulator,
660624
reason: reason,
661-
benchmarkMode: benchmarkMode,
662625
silent: silent,
663626
);
664627
if (!silent) {
@@ -687,7 +650,6 @@ class HotRunner extends ResidentRunner {
687650
String sdkName,
688651
bool emulator,
689652
String reason,
690-
bool benchmarkMode,
691653
bool silent,
692654
}) async {
693655
if (!canHotRestart) {
@@ -713,7 +675,6 @@ class HotRunner extends ResidentRunner {
713675
// handling, at least until we can refactor the underlying code.
714676
result = await asyncGuard(() => _restartFromSources(
715677
reason: reason,
716-
benchmarkMode: benchmarkMode,
717678
));
718679
if (!result.isOk) {
719680
restartEvent = 'restart-failed';

0 commit comments

Comments
 (0)