Unverified Commit 52bd2ccb authored by Alexander Aprelev's avatar Alexander Aprelev Committed by GitHub

Report devfs stats (#25586)

* Collect devfs stats for better analytics

* Fix fields initialization

* Fix lints
parent 50f9b883
...@@ -350,6 +350,32 @@ class _DevFSHttpWriter { ...@@ -350,6 +350,32 @@ class _DevFSHttpWriter {
} }
} }
// Basic statistics for DevFS update operation.
class UpdateFSReport {
UpdateFSReport({bool success = false,
int invalidatedSourcesCount = 0, int syncedBytes = 0}) {
_success = success;
_invalidatedSourcesCount = invalidatedSourcesCount;
_syncedBytes = syncedBytes;
}
bool get success => _success;
int get invalidatedSourcesCount => _invalidatedSourcesCount;
int get syncedBytes => _syncedBytes;
void incorporateResults(UpdateFSReport report) {
if (!report._success) {
_success = false;
}
_invalidatedSourcesCount += report._invalidatedSourcesCount;
_syncedBytes += report._syncedBytes;
}
bool _success;
int _invalidatedSourcesCount;
int _syncedBytes;
}
class DevFS { class DevFS {
/// Create a [DevFS] named [fsName] for the local files in [rootDirectory]. /// Create a [DevFS] named [fsName] for the local files in [rootDirectory].
DevFS(VMService serviceProtocol, DevFS(VMService serviceProtocol,
...@@ -422,7 +448,7 @@ class DevFS { ...@@ -422,7 +448,7 @@ class DevFS {
/// Updates files on the device. /// Updates files on the device.
/// ///
/// Returns the number of bytes synced. /// Returns the number of bytes synced.
Future<int> update({ Future<UpdateFSReport> update({
@required String mainPath, @required String mainPath,
String target, String target,
AssetBundle bundle, AssetBundle bundle,
...@@ -487,7 +513,7 @@ class DevFS { ...@@ -487,7 +513,7 @@ class DevFS {
} }
// Update modified files // Update modified files
int numBytes = 0; int syncedBytes = 0;
final Map<Uri, DevFSContent> dirtyEntries = <Uri, DevFSContent>{}; final Map<Uri, DevFSContent> dirtyEntries = <Uri, DevFSContent>{};
_entries.forEach((Uri deviceUri, DevFSContent content) { _entries.forEach((Uri deviceUri, DevFSContent content) {
String archivePath; String archivePath;
...@@ -498,7 +524,7 @@ class DevFS { ...@@ -498,7 +524,7 @@ class DevFS {
// files to incremental compiler next time user does hot reload. // files to incremental compiler next time user does hot reload.
if (content.isModified || ((bundleDirty || bundleFirstUpload) && archivePath != null)) { if (content.isModified || ((bundleDirty || bundleFirstUpload) && archivePath != null)) {
dirtyEntries[deviceUri] = content; dirtyEntries[deviceUri] = content;
numBytes += content.size; syncedBytes += content.size;
if (archivePath != null && (!bundleFirstUpload || content.isModifiedAfter(firstBuildTime))) if (archivePath != null && (!bundleFirstUpload || content.isModifiedAfter(firstBuildTime)))
assetPathsToEvict.add(archivePath); assetPathsToEvict.add(archivePath);
} }
...@@ -516,7 +542,7 @@ class DevFS { ...@@ -516,7 +542,7 @@ class DevFS {
if (content is DevFSFileContent) { if (content is DevFSFileContent) {
filesUris.add(uri); filesUris.add(uri);
invalidatedFiles.add(content.file.uri.toString()); invalidatedFiles.add(content.file.uri.toString());
numBytes -= content.size; syncedBytes -= content.size;
} }
} }
} }
...@@ -545,7 +571,7 @@ class DevFS { ...@@ -545,7 +571,7 @@ class DevFS {
if (!dirtyEntries.containsKey(entryUri)) { if (!dirtyEntries.containsKey(entryUri)) {
final DevFSFileContent content = DevFSFileContent(fs.file(compiledBinary)); final DevFSFileContent content = DevFSFileContent(fs.file(compiledBinary));
dirtyEntries[entryUri] = content; dirtyEntries[entryUri] = content;
numBytes += content.size; syncedBytes += content.size;
} }
} }
} }
...@@ -576,7 +602,8 @@ class DevFS { ...@@ -576,7 +602,8 @@ class DevFS {
} }
printTrace('DevFS: Sync finished'); printTrace('DevFS: Sync finished');
return numBytes; return UpdateFSReport(success: true, syncedBytes: syncedBytes,
invalidatedSourcesCount: invalidatedFiles.length);
} }
void _scanFile(Uri deviceUri, FileSystemEntity file) { void _scanFile(Uri deviceUri, FileSystemEntity file) {
......
...@@ -368,7 +368,7 @@ class FlutterDevice { ...@@ -368,7 +368,7 @@ class FlutterDevice {
return 0; return 0;
} }
Future<bool> updateDevFS({ Future<UpdateFSReport> updateDevFS({
String mainPath, String mainPath,
String target, String target,
AssetBundle bundle, AssetBundle bundle,
...@@ -384,9 +384,9 @@ class FlutterDevice { ...@@ -384,9 +384,9 @@ class FlutterDevice {
'Syncing files to device ${device.name}...', 'Syncing files to device ${device.name}...',
expectSlowOperation: true, expectSlowOperation: true,
); );
int bytes = 0; UpdateFSReport report;
try { try {
bytes = await devFS.update( report = await devFS.update(
mainPath: mainPath, mainPath: mainPath,
target: target, target: target,
bundle: bundle, bundle: bundle,
...@@ -403,11 +403,11 @@ class FlutterDevice { ...@@ -403,11 +403,11 @@ class FlutterDevice {
); );
} on DevFSException { } on DevFSException {
devFSStatus.cancel(); devFSStatus.cancel();
return false; return UpdateFSReport(success: false);
} }
devFSStatus.stop(); devFSStatus.stop();
printTrace('Synced ${getSizeAsMB(bytes)}.'); printTrace('Synced ${getSizeAsMB(report.syncedBytes)}.');
return true; return report;
} }
void updateReloadStatus(bool wasReloadSuccessful) { void updateReloadStatus(bool wasReloadSuccessful) {
......
...@@ -19,6 +19,7 @@ import 'build_info.dart'; ...@@ -19,6 +19,7 @@ import 'build_info.dart';
import 'compile.dart'; import 'compile.dart';
import 'dart/dependencies.dart'; import 'dart/dependencies.dart';
import 'dart/pub.dart'; import 'dart/pub.dart';
import 'devfs.dart';
import 'device.dart'; import 'device.dart';
import 'globals.dart'; import 'globals.dart';
import 'resident_runner.dart'; import 'resident_runner.dart';
...@@ -193,12 +194,12 @@ class HotRunner extends ResidentRunner { ...@@ -193,12 +194,12 @@ class HotRunner extends ResidentRunner {
return 3; return 3;
} }
final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start(); final Stopwatch initialUpdateDevFSsTimer = Stopwatch()..start();
final bool devfsResult = await _updateDevFS(fullRestart: true); final UpdateFSReport devfsResult = await _updateDevFS(fullRestart: true);
_addBenchmarkData( _addBenchmarkData(
'hotReloadInitialDevFSSyncMilliseconds', 'hotReloadInitialDevFSSyncMilliseconds',
initialUpdateDevFSsTimer.elapsed.inMilliseconds, initialUpdateDevFSsTimer.elapsed.inMilliseconds,
); );
if (!devfsResult) if (!devfsResult.success)
return 3; return 3;
await refreshViews(); await refreshViews();
...@@ -329,10 +330,10 @@ class HotRunner extends ResidentRunner { ...@@ -329,10 +330,10 @@ class HotRunner extends ResidentRunner {
return devFSUris; return devFSUris;
} }
Future<bool> _updateDevFS({ bool fullRestart = false }) async { Future<UpdateFSReport> _updateDevFS({ bool fullRestart = false }) async {
if (!await _refreshDartDependencies()) { if (!await _refreshDartDependencies()) {
// Did not update DevFS because of a Dart source error. // Did not update DevFS because of a Dart source error.
return false; return UpdateFSReport(success: false);
} }
final bool isFirstUpload = assetBundle.wasBuiltOnce() == false; final bool isFirstUpload = assetBundle.wasBuiltOnce() == false;
final bool rebuildBundle = assetBundle.needsBuild(); final bool rebuildBundle = assetBundle.needsBuild();
...@@ -340,12 +341,12 @@ class HotRunner extends ResidentRunner { ...@@ -340,12 +341,12 @@ class HotRunner extends ResidentRunner {
printTrace('Updating assets'); printTrace('Updating assets');
final int result = await assetBundle.build(); final int result = await assetBundle.build();
if (result != 0) if (result != 0)
return false; return UpdateFSReport(success: false);
} }
final List<bool> results = <bool>[]; final UpdateFSReport results = UpdateFSReport(success: true);
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
results.add(await device.updateDevFS( results.incorporateResults(await device.updateDevFS(
mainPath: mainPath, mainPath: mainPath,
target: target, target: target,
bundle: assetBundle, bundle: assetBundle,
...@@ -358,16 +359,15 @@ class HotRunner extends ResidentRunner { ...@@ -358,16 +359,15 @@ class HotRunner extends ResidentRunner {
pathToReload: getReloadPath(fullRestart: fullRestart), pathToReload: getReloadPath(fullRestart: fullRestart),
)); ));
} }
// If there any failures reported, bail out. if (!results.success) {
if (results.any((bool result) => !result)) { return results;
return false;
} }
if (!hotRunnerConfig.stableDartDependencies) { if (!hotRunnerConfig.stableDartDependencies) {
// Clear the set after the sync so they are recomputed next time. // Clear the set after the sync so they are recomputed next time.
_dartDependencies = null; _dartDependencies = null;
} }
return true; return results;
} }
Future<void> _evictDirtyAssets() { Future<void> _evictDirtyAssets() {
...@@ -460,8 +460,8 @@ class HotRunner extends ResidentRunner { ...@@ -460,8 +460,8 @@ class HotRunner extends ResidentRunner {
final Stopwatch restartTimer = Stopwatch()..start(); final Stopwatch restartTimer = Stopwatch()..start();
// TODO(aam): Add generator reset logic once we switch to using incremental // TODO(aam): Add generator reset logic once we switch to using incremental
// compiler for full application recompilation on restart. // compiler for full application recompilation on restart.
final bool updatedDevFS = await _updateDevFS(fullRestart: true); final UpdateFSReport updatedDevFS = await _updateDevFS(fullRestart: true);
if (!updatedDevFS) { if (!updatedDevFS.success) {
for (FlutterDevice device in flutterDevices) { for (FlutterDevice device in flutterDevices) {
if (device.generator != null) if (device.generator != null)
device.generator.reject(); device.generator.reject();
...@@ -618,11 +618,11 @@ class HotRunner extends ResidentRunner { ...@@ -618,11 +618,11 @@ class HotRunner extends ResidentRunner {
final Stopwatch reloadTimer = Stopwatch()..start(); final Stopwatch reloadTimer = Stopwatch()..start();
final Stopwatch devFSTimer = Stopwatch()..start(); final Stopwatch devFSTimer = Stopwatch()..start();
final bool updatedDevFS = await _updateDevFS(); final UpdateFSReport updatedDevFS = await _updateDevFS();
// Record time it took to synchronize to DevFS. // Record time it took to synchronize to DevFS.
_addBenchmarkData('hotReloadDevFSSyncMilliseconds', _addBenchmarkData('hotReloadDevFSSyncMilliseconds',
devFSTimer.elapsed.inMilliseconds); devFSTimer.elapsed.inMilliseconds);
if (!updatedDevFS) if (!updatedDevFS.success)
return OperationResult(1, 'DevFS synchronization failed'); return OperationResult(1, 'DevFS synchronization failed');
String reloadMessage; String reloadMessage;
final Stopwatch vmReloadTimer = Stopwatch()..start(); final Stopwatch vmReloadTimer = Stopwatch()..start();
......
This diff is collapsed.
...@@ -112,7 +112,8 @@ void main() { ...@@ -112,7 +112,8 @@ void main() {
trackWidgetCreation: anyNamed('trackWidgetCreation'), trackWidgetCreation: anyNamed('trackWidgetCreation'),
projectRootPath: anyNamed('projectRootPath'), projectRootPath: anyNamed('projectRootPath'),
pathToReload: anyNamed('pathToReload'), pathToReload: anyNamed('pathToReload'),
)).thenAnswer((Invocation _) => Future<int>.value(1000)); )).thenAnswer((Invocation _) => Future<UpdateFSReport>.value(
UpdateFSReport(success: true, syncedBytes: 1000, invalidatedSourcesCount: 1)));
when(mockDevFs.assetPathsToEvict).thenReturn(Set<String>()); when(mockDevFs.assetPathsToEvict).thenReturn(Set<String>());
when(mockDevFs.baseUri).thenReturn(Uri.file('test')); when(mockDevFs.baseUri).thenReturn(Uri.file('test'));
......
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