Repository navigation
[kernel/flutter] Improve speed of first hot reload - #13699
Conversation
|
The first hot reload is the second upload of the images, no? The app has already been running for a while by then and has fetched images from its asset bundle. This needs a test. The best test would be good to create a devicelab end-to-end test that verifies that hot reload successfully changes the assets (e.g. you could check if the dimensions of an image change after the image has been changed on disk and a hot reload triggered, checking the dimensions on initial load, after the initial hot reload, and after a second hot reload). |
|
Maybe I didn't explain properly (or I didn't quite understand your comment). For a normal hot reload scenario, what's happening is this:
For the initial upload what's happening is this:
What should happen - it seems to me - on the initial upload is this:
or, alternatively, and what I've changed the PR to be because it seems cleaner:
This seems reasonable to me: I'm all for adding tests, but a) I don't know how tests work in flutter, any pointers would be appreciated, and b) it seems to me that #7302 will block such a test... |
|
There's three kinds of loads:
The first happens when you first call We need to evict everything after the second, unless we know that it hasn't changed between 1 and 2. |
|
cc @aam |
Sure. But the same applies for between 2 and 3 (where there is no 'carry-over'), and another way to say "everything but unchanged" is to say "changed", and if a file isn't re-uploaded as part of "2" it haven't changed, so it shouldn't be evicted. |
|
If I understand correctly, flutter tools keeps track of changes to the assets after 2, but the way things are now, it doesn't know what changed between 1 and 2 - potentially content of archive created for 1 is outdated by the time 2 is requested. So when 2(first hot reload) is requested, it evicts and forces reload of all assets. |
If that was the case it would also have to re-upload the same assets. Am I reading this code wrong? flutter/packages/flutter_tools/lib/src/devfs.dart Lines 439 to 454 in 45289c0 What I'm reading is this:
Then further down the entries in To me that means that one of two things are happening:
In both cases however, Btw, printing the content of |
|
First time code quoted above is executed it will add all files and assets to the dirty list, yes. |
|
So what you're saying is that any change to the assets between the packaging of the files into a bundle (apk/ipa) to the initial upload will have to be evicted? So the process actually looks something like this:
So a test that will make this PR fail would be this:
And a way to change this PR to pass the above-sketched test would be to instead:
I.e. instead of clearing the evict list after uploading everything (as this PR currently does), then in the first place only record things as having to be evicted if they have changed since the first-recorded time? Does that sound reasonable? |
Yeah, something along these lines. This was recently mentioned in the context of hot reload initial sync getting slower here: dart-lang/sdk#31669 (comment). There is also #7946 for this which has more ideas and discussions on this topic. |
|
@jensjoha Are you planning on making the updates you suggested? Should we close the PR in the meantime to keep it off the "pending review" queue? |
|
I made a first stab at the suggested algorithm. I here include some timings on a real device (Nexus 4), though on a non-updated flutter/engine. I will update and redo them... Now (--preview-dart-2): Now (without --preview-dart-2): Before (--preview-dart-2): Before (without --preview-dart-2): |
|
Timings after rebase: Nexus 4, preview dart 2, with vs without First: 1,914ms. vs 6,606ms. (~29%) Nexus 4, without preview dart 2, with vs without First: 9,174ms. vs 13,254ms. (~69%) x64 Android emulator, preview dart 2, with vs without First: 747ms. vs 2,002ms. (~37%) x64 Android emulator, without preview dart 2, with vs without First: 1,481ms. vs 1,840ms. (~80%) |
| } | ||
| } | ||
|
|
||
| bool wasBuildOnce() => _lastBuildTimestamp != null; |
There was a problem hiding this comment.
nit: "wasBuiltOnce" is more gramatically correct, I think?
|
Any new thoughts on this? |
|
Sorry, I'm not following how you record the time when APK was built. |
|
This change basically records the time before doing anything else (https://github.com/flutter/flutter/pull/13699/files#diff-e78651ad5bd5c46811f2b76bc465220bR217). This way any change made to an asset in the gap between apk build and initial upload will have a newer timestamp upon upload, thus being added to the list of assets to evict. |
|
Ah, thanks for the explanation. lgtm. |
|
Merge conflicts fixed. |
|
Somehow I don't see any impact on hot_mode_dev_cycle__preview_dart_2 benchmarks on https://flutter-dashboard.appspot.com/benchmarks.html |
|
The benchmarked data is not the first hot reload. It is basically the second hot reload (it might be a hot reload after a hot restart) - but the first hot reload is not measured in the benchmark. If you manually do a "flutter run --preview-dart-2" and press "r" you should definitely see the difference on the first hot reload (compared to before). |
|
Got you, thanks! |
* [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 f3dc133. * Revert "[kernel/flutter] Improve speed of first hot reload" This reverts commit f7bcb08. * Revert "Revert "[kernel/flutter] Improve speed of first hot reload"" This reverts commit 73c7a1a. * [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
Running "flutter run --local-engine=android_debug --preview-dart-2" in flutter_gallery and performing a hot-reload takes ~2000 ms the first time and ~500 ms subsequent times. The majority of this overhead is caused by "evict" calls on all assets which doesn't seems necessary - how could they be cached if we just uploaded them to the phone?
This PR handles the first-time upload differently so "evict" is not called unnecessarily.
Note that the numbers above are from running it on an emulator.