Commit b314fa59 authored by John McCutchan's avatar John McCutchan Committed by GitHub

Add time to frame tracking to hot run (#5316)

parent 2075816d
...@@ -78,6 +78,15 @@ String getSizeAsMB(int bytesLength) { ...@@ -78,6 +78,15 @@ String getSizeAsMB(int bytesLength) {
return '${(bytesLength / (1024 * 1024)).toStringAsFixed(1)}MB'; return '${(bytesLength / (1024 * 1024)).toStringAsFixed(1)}MB';
} }
String getElapsedAsSeconds(Duration duration) {
double seconds = duration.inMilliseconds / Duration.MILLISECONDS_PER_SECOND;
return '${seconds.toStringAsFixed(2)} seconds';
}
String getElapsedAsMilliseconds(Duration duration) {
return '${duration.inMilliseconds} ms';
}
/// Return a relative path if [fullPath] is contained by the cwd, else return an /// Return a relative path if [fullPath] is contained by the cwd, else return an
/// absolute path. /// absolute path.
String getDisplayPath(String fullPath) { String getDisplayPath(String fullPath) {
......
...@@ -29,6 +29,41 @@ String getDevFSLoaderScript() { ...@@ -29,6 +29,41 @@ String getDevFSLoaderScript() {
'loader_app.dart')); 'loader_app.dart'));
} }
class FirstFrameTimer {
FirstFrameTimer(this.serviceProtocol);
void start() {
stopwatch.reset();
stopwatch.start();
_subscription = serviceProtocol.onExtensionEvent.listen(_onExtensionEvent);
}
/// Returns a Future which completes after the first frame event is received.
Future<Null> firstFrame() => _completer.future;
void _onExtensionEvent(Event event) {
if (event.extensionKind == 'Flutter.FirstFrame')
_stop();
}
void _stop() {
_subscription?.cancel();
_subscription = null;
stopwatch.stop();
_completer.complete(null);
}
Duration get elapsed {
assert(!stopwatch.isRunning);
return stopwatch.elapsed;
}
final Observatory serviceProtocol;
final Stopwatch stopwatch = new Stopwatch();
final Completer<Null> _completer = new Completer<Null>();
StreamSubscription<Event> _subscription;
}
class HotRunner extends ResidentRunner { class HotRunner extends ResidentRunner {
HotRunner( HotRunner(
Device device, { Device device, {
...@@ -347,16 +382,21 @@ class HotRunner extends ResidentRunner { ...@@ -347,16 +382,21 @@ class HotRunner extends ResidentRunner {
} }
Future<Null> _restartFromSources() async { Future<Null> _restartFromSources() async {
FirstFrameTimer firstFrameTimer = new FirstFrameTimer(serviceProtocol);
firstFrameTimer.start();
if (_devFS == null) { if (_devFS == null) {
Status restartStatus = logger.startProgress('Restarting application...');
await _launchFromDisk(_package, _mainPath); await _launchFromDisk(_package, _mainPath);
restartStatus.stop(showElapsedTime: true);
} else { } else {
await _updateDevFS(); await _updateDevFS();
Status restartStatus = logger.startProgress('Restarting application...');
await _launchFromDevFS(_package, _mainPath); await _launchFromDevFS(_package, _mainPath);
restartStatus.stop(showElapsedTime: true);
} }
Status restartStatus =
logger.startProgress('Waiting for application to start...');
// Wait for the first frame to be rendered.
await firstFrameTimer.firstFrame();
restartStatus.stop(showElapsedTime: true);
printStatus('Restart time: '
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}');
flutterUsage.sendEvent('hot', 'restart'); flutterUsage.sendEvent('hot', 'restart');
} }
...@@ -380,6 +420,8 @@ class HotRunner extends ResidentRunner { ...@@ -380,6 +420,8 @@ class HotRunner extends ResidentRunner {
Future<bool> _reloadSources() async { Future<bool> _reloadSources() async {
if (serviceProtocol.firstIsolateId == null) if (serviceProtocol.firstIsolateId == null)
throw 'Application isolate not found'; throw 'Application isolate not found';
FirstFrameTimer firstFrameTimer = new FirstFrameTimer(serviceProtocol);
firstFrameTimer.start();
if (_devFS != null) if (_devFS != null)
await _updateDevFS(); await _updateDevFS();
Status reloadStatus = logger.startProgress('Performing hot reload...'); Status reloadStatus = logger.startProgress('Performing hot reload...');
...@@ -410,6 +452,9 @@ class HotRunner extends ResidentRunner { ...@@ -410,6 +452,9 @@ class HotRunner extends ResidentRunner {
return false; return false;
} }
reassembleStatus.stop(showElapsedTime: true); reassembleStatus.stop(showElapsedTime: true);
await firstFrameTimer.firstFrame();
printStatus('Hot reload time: '
'${getElapsedAsMilliseconds(firstFrameTimer.elapsed)}');
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment