[kernel/flutter] Improve speed of first hot reload (#13699)
* [kernel/flutter] Improve speed of first hot reload
* [kernel/flutter] Improve speed of first hot reload
* Revert "[kernel/flutter] Improve speed of first hot reload"
This reverts commit f3dc133878ec7405a8efb5715f1cfe720f4ea05f.
* Revert "[kernel/flutter] Improve speed of first hot reload"
This reverts commit f7bcb082b01cf9cf48f02c6aad9e5c79705def8f.
* Revert "Revert "[kernel/flutter] Improve speed of first hot reload""
This reverts commit 73c7a1a8e85a4c0397984d8b65a98b2f71bf84f3.
* [kernel/flutter] Improve speed of first hot reload
Do so by not evicting unnecessary paths (while still evicting paths
that was changed between the generation of the package file and the
initial upload).
* Fix grammar in method name
* Fix bad merge
* Add method to super class
diff --git a/packages/flutter_tools/lib/src/asset.dart b/packages/flutter_tools/lib/src/asset.dart
index a49c084..8d9a751 100644
--- a/packages/flutter_tools/lib/src/asset.dart
+++ b/packages/flutter_tools/lib/src/asset.dart
@@ -35,6 +35,8 @@
Map<String, DevFSContent> get entries;
+ bool wasBuiltOnce();
+
bool needsBuild({String manifestPath: _ManifestAssetBundle.defaultManifestPath});
/// Returns 0 for success; non-zero for failure.
@@ -90,6 +92,9 @@
}
@override
+ bool wasBuiltOnce() => _lastBuildTimestamp != null;
+
+ @override
bool needsBuild({String manifestPath: defaultManifestPath}) {
if (_fixed)
return false;
diff --git a/packages/flutter_tools/lib/src/devfs.dart b/packages/flutter_tools/lib/src/devfs.dart
index 96711f6..6882208 100644
--- a/packages/flutter_tools/lib/src/devfs.dart
+++ b/packages/flutter_tools/lib/src/devfs.dart
@@ -34,6 +34,11 @@
/// or if the entry has been modified since this method was last called.
bool get isModified;
+ /// Return true if this is the first time this method is called
+ /// or if the entry has been modified after the given time
+ /// or if the given time is null.
+ bool isModifiedAfter(DateTime time);
+
int get size;
Future<List<int>> contentsAsBytes();
@@ -104,6 +109,13 @@
}
@override
+ bool isModifiedAfter(DateTime time) {
+ final FileStat _oldFileStat = _fileStat;
+ _stat();
+ return _oldFileStat == null || time == null || _fileStat.modified.isAfter(time);
+ }
+
+ @override
int get size {
if (_fileStat == null)
_stat();
@@ -124,12 +136,14 @@
List<int> _bytes;
bool _isModified = true;
+ DateTime _modificationTime = new DateTime.now();
List<int> get bytes => _bytes;
set bytes(List<int> value) {
_bytes = value;
_isModified = true;
+ _modificationTime = new DateTime.now();
}
/// Return true only once so that the content is written to the device only once.
@@ -141,6 +155,11 @@
}
@override
+ bool isModifiedAfter(DateTime time) {
+ return time == null || _modificationTime.isAfter(time);
+ }
+
+ @override
int get size => _bytes.length;
@override
@@ -383,6 +402,8 @@
String mainPath,
String target,
AssetBundle bundle,
+ DateTime firstBuildTime,
+ bool bundleFirstUpload: false,
bool bundleDirty: false,
Set<String> fileFilter,
ResidentCompiler generator,
@@ -445,10 +466,10 @@
// that isModified does not reset last check timestamp because we
// want to report all modified files to incremental compiler next time
// user does hot reload.
- if (content.isModified || (bundleDirty && archivePath != null)) {
+ if (content.isModified || ((bundleDirty || bundleFirstUpload) && archivePath != null)) {
dirtyEntries[deviceUri] = content;
numBytes += content.size;
- if (archivePath != null)
+ if (archivePath != null && (!bundleFirstUpload || content.isModifiedAfter(firstBuildTime)))
assetPathsToEvict.add(archivePath);
}
});
diff --git a/packages/flutter_tools/lib/src/resident_runner.dart b/packages/flutter_tools/lib/src/resident_runner.dart
index 3f42d0b..a7c520a 100644
--- a/packages/flutter_tools/lib/src/resident_runner.dart
+++ b/packages/flutter_tools/lib/src/resident_runner.dart
@@ -365,6 +365,8 @@
String mainPath,
String target,
AssetBundle bundle,
+ DateTime firstBuildTime,
+ bool bundleFirstUpload: false,
bool bundleDirty: false,
Set<String> fileFilter,
bool fullRestart: false
@@ -379,6 +381,8 @@
mainPath: mainPath,
target: target,
bundle: bundle,
+ firstBuildTime: firstBuildTime,
+ bundleFirstUpload: bundleFirstUpload,
bundleDirty: bundleDirty,
fileFilter: fileFilter,
generator: generator,
diff --git a/packages/flutter_tools/lib/src/run_hot.dart b/packages/flutter_tools/lib/src/run_hot.dart
index a4000ad..039f440 100644
--- a/packages/flutter_tools/lib/src/run_hot.dart
+++ b/packages/flutter_tools/lib/src/run_hot.dart
@@ -66,6 +66,7 @@
// The initial launch is from a snapshot.
bool _runningFromSnapshot = true;
bool previewDart2 = false;
+ DateTime firstBuildTime;
bool strongMode = false;
void _addBenchmarkData(String name, int value) {
@@ -213,6 +214,8 @@
return 1;
}
+ firstBuildTime = new DateTime.now();
+
for (FlutterDevice device in flutterDevices) {
final int result = await device.runHot(
hotRunner: this,
@@ -262,6 +265,7 @@
// Did not update DevFS because of a Dart source error.
return false;
}
+ final bool isFirstUpload = assetBundle.wasBuiltOnce() == false;
final bool rebuildBundle = assetBundle.needsBuild();
if (rebuildBundle) {
printTrace('Updating assets');
@@ -275,7 +279,9 @@
mainPath: mainPath,
target: target,
bundle: assetBundle,
- bundleDirty: rebuildBundle,
+ firstBuildTime: firstBuildTime,
+ bundleFirstUpload: isFirstUpload,
+ bundleDirty: isFirstUpload == false && rebuildBundle,
fileFilter: _dartDependencies,
fullRestart: fullRestart
);