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