Skip to content

fix(tool): initialize asset isModified state on startup to prevent 2x hot restart slowdown#187488

Merged
auto-submit[bot] merged 5 commits into
flutter:masterfrom
kevmoo:i187391_hot_slow
Jun 5, 2026
Merged

fix(tool): initialize asset isModified state on startup to prevent 2x hot restart slowdown#187488
auto-submit[bot] merged 5 commits into
flutter:masterfrom
kevmoo:i187391_hot_slow

Conversation

@kevmoo

@kevmoo kevmoo commented Jun 3, 2026

Copy link
Copy Markdown
Contributor

Prior to this fix, the first hot restart would incorrectly detect all assets as modified and sync/recompile all of them. This was because DevFS.updateBundle bypassed the asset loop during the initial application startup, which prevented the stateful isModified getter from being initialized.

This fix accesses isModified for each asset in the bundle during startup to initialize the cache, matching the behavior before the asset processing refactor.

Fixes #187391

… hot restart slowdown

Prior to this fix, the first hot restart would incorrectly detect all assets as modified and sync/recompile all of them. This was because DevFS.updateBundle bypassed the asset loop during the initial application startup, which prevented the stateful isModified getter from being initialized.

This fix accesses isModified for each asset in the bundle during startup to initialize the cache, matching the behavior before the asset processing refactor.

Fixes flutter#187391
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 3, 2026
@github-actions github-actions Bot added the tool Affects the "flutter" command-line tool. See also t: labels. label Jun 3, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request updates DevFS.updateBundle to initialize the isModified state of assets during the first upload when syncing is skipped, preventing unnecessary recompilation on subsequent hot restarts. A corresponding test was added to verify this behavior. The review feedback suggests simplifying the asset iteration in DevFS.updateBundle by iterating directly over bundle.entries.values instead of bundle.entries.entries since the keys are not used.

Comment thread packages/flutter_tools/lib/src/devfs.dart Outdated
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 3, 2026

@harryterkelsen harryterkelsen left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let’s just change isModified to be what people would expect instead of doing this partial solution. To me, it seems odd for isModified to not be idempotent.

Comment thread packages/flutter_tools/lib/src/devfs.dart Outdated
Comment thread packages/flutter_tools/lib/src/devfs.dart
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 4, 2026
@kevmoo

kevmoo commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

@harryterkelsen PTAL

@kevmoo kevmoo requested a review from harryterkelsen June 4, 2026 18:25
@github-actions github-actions Bot removed the CICD Run CI/CD label Jun 4, 2026
@kevmoo

kevmoo commented Jun 4, 2026

Copy link
Copy Markdown
Contributor Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors DevFSContent and its subclasses to decouple the isModified check from state mutation by introducing an explicit markClean() method. It also updates DevFS.updateBundle and associated tests to manage this lifecycle. The review feedback identifies two critical issues: a regression in isModifiedAfter that prevents the detection of deleted files, and an unintended state mutation in the size getter due to calling markClean(), which can cause modified files to be skipped during synchronization.

Comment thread packages/flutter_tools/lib/src/devfs.dart
Comment thread packages/flutter_tools/lib/src/devfs.dart Outdated
@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Jun 4, 2026
@kevmoo

kevmoo commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

I had to do the google3 dance, but I think we're ready @harryterkelsen !

@kevmoo kevmoo added the autosubmit Merge PR when tree becomes green via auto submit App label Jun 5, 2026
@auto-submit auto-submit Bot added this pull request to the merge queue Jun 5, 2026
Merged via the queue into flutter:master with commit 1e492c7 Jun 5, 2026
165 of 166 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Jun 5, 2026
@kevmoo kevmoo deleted the i187391_hot_slow branch June 5, 2026 22:17
passsy added a commit to passsy/flutter that referenced this pull request Jun 9, 2026
DevFSFileContent.isModifiedAfter returned true whenever the cached
_fileStat was null, ignoring the time argument entirely. _fileStat is the
sync baseline written only by markClean(); the entries of a freshly built
AssetBundle are never marked clean, so _fileStat is always null for them
and isModifiedAfter always reported them as modified.

flutter test's _needsRebuild() relies on isModifiedAfter to decide
whether build/unit_test_assets is up to date. With the broken short
circuit it always rebuilt the directory (delete + non-atomic rewrite) on
every invocation. When several flutter test invocations run in the same
project directory, one invocation's delete window overlaps another's
asset reads, surfacing as a transient

    Exception: Asset 'shaders/ink_sparkle.frag' not found

that fails an unrelated test.

isModifiedAfter is handed an explicit reference time and must not consult
the sync baseline. Determine modification purely from the file's current
modification time, matching the other DevFSContent implementations.

Regression from flutter#187488, which made the stat accessors pure. Before that
the mutating _stat() populated _fileStat as a side effect of reads during
the asset build, so _needsRebuild happened to work. Fixes
flutter#187725.
passsy added a commit to passsy/flutter that referenced this pull request Jun 9, 2026
DevFSFileContent.isModifiedAfter returned true whenever the cached
_fileStat was null, ignoring the time argument entirely. _fileStat is the
sync baseline written only by markClean(); the entries of a freshly built
AssetBundle are never marked clean, so _fileStat is always null for them
and isModifiedAfter always reported them as modified.

flutter test's _needsRebuild() relies on isModifiedAfter to decide
whether build/unit_test_assets is up to date. With the broken short
circuit it always rebuilt the directory (delete + non-atomic rewrite) on
every invocation. When several flutter test invocations run in the same
project directory, one invocation's delete window overlaps another's
asset reads, surfacing as a transient

    Exception: Asset 'shaders/ink_sparkle.frag' not found

that fails an unrelated test.

isModifiedAfter is handed an explicit reference time and must not consult
the sync baseline. Determine modification purely from the file's current
modification time, matching the other DevFSContent implementations.

Regression from flutter#187488, which made the stat accessors pure. Before that
the mutating _stat() populated _fileStat as a side effect of reads during
the asset build, so _needsRebuild happened to work. Fixes
flutter#187725.
auto-submit Bot pushed a commit to flutter/packages that referenced this pull request Jun 10, 2026
flutter/flutter@1bdf4af...66aaa9a

2026-06-08 katelovett@google.com Add docs on bumping Dart (flutter/flutter#187540)
2026-06-08 rmacnak@google.com Rename Dart_LoadELF2 back to Dart_LoadELF. (flutter/flutter#187677)
2026-06-08 1063596+reidbaker@users.noreply.github.com Add bare, reidbaker, and android agents (flutter/flutter#187588)
2026-06-08 engine-flutter-autoroll@skia.org Roll Dart SDK from 73ec2745c49a to 39f1c44e294f (3 revisions) (flutter/flutter#187684)
2026-06-08 bdero@google.com [Flutter GPU] Document the formats.dart enums (flutter/flutter#187628)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from 0ea3dae686e3 to 43f135735152 (3 revisions) (flutter/flutter#187683)
2026-06-08 bdero@google.com [flutter_tools] Fix `flutter create` crash with SDK packages in bin/cache/pkg (flutter/flutter#187653)
2026-06-08 engine-flutter-autoroll@skia.org Roll Packages from 61bdbb4 to 13b49f4 (1 revision) (flutter/flutter#187678)
2026-06-08 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from fAGotRbStYGA0idum... to KNe93cf5wU4xG2d-m... (flutter/flutter#187675)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from d17c51db4ede to 0ea3dae686e3 (1 revision) (flutter/flutter#187674)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from 9659a87f500f to d17c51db4ede (2 revisions) (flutter/flutter#187672)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from a56d5a4e1120 to 9659a87f500f (1 revision) (flutter/flutter#187667)
2026-06-07 engine-flutter-autoroll@skia.org Roll Skia from 101faf7d9d1f to a56d5a4e1120 (1 revision) (flutter/flutter#187665)
2026-06-07 burak.karahan@mail.ru Remove Material import from navigator replacement tests (flutter/flutter#186674)
2026-06-07 burak.karahan@mail.ru Remove Material import from editable text cursor tests (flutter/flutter#186671)
2026-06-07 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from eIU3QDrxaBPAMY9oi... to fAGotRbStYGA0idum... (flutter/flutter#187656)
2026-06-07 engine-flutter-autoroll@skia.org Roll Skia from 294ac0cb2a7d to 101faf7d9d1f (1 revision) (flutter/flutter#187655)
2026-06-06 engine-flutter-autoroll@skia.org Roll Skia from 91ee612cf552 to 294ac0cb2a7d (2 revisions) (flutter/flutter#187651)
2026-06-06 engine-flutter-autoroll@skia.org Roll Skia from a47a9a2c8ae5 to 91ee612cf552 (4 revisions) (flutter/flutter#187642)
2026-06-06 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from N_LiSaBSUsE2LDZgG... to eIU3QDrxaBPAMY9oi... (flutter/flutter#187641)
2026-06-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 05243f181c21 to 73ec2745c49a (2 revisions) (flutter/flutter#187640)
2026-06-06 engine-flutter-autoroll@skia.org Roll Fuchsia GN SDK from oOAcFhkoE2_-Sy67z... to a87CbQSWEjkPUK1ZY... (flutter/flutter#187632)
2026-06-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 6a9a0efe66eb to 05243f181c21 (1 revision) (flutter/flutter#187634)
2026-06-05 bdero@google.com [Flutter GPU] Add instanced draw support (flutter/flutter#187359)
2026-06-05 30870216+gaaclarke@users.noreply.github.com clears out the android context after the frame on mediatek devices (flutter/flutter#187404)
2026-06-05 kevmoo@users.noreply.github.com fix(tool): initialize asset isModified state on startup to prevent 2x hot restart slowdown (flutter/flutter#187488)
2026-06-05 magder@google.com Remove reference to 'good first issue' in the docs (flutter/flutter#187615)
2026-06-05 stuartmorgan@google.com Remove references to 'good first issue' (flutter/flutter#187617)
2026-06-05 154381524+flutteractionsbot@users.noreply.github.com Revert "Add support for stylus buttons" (flutter/flutter#187581)
2026-06-05 6655696+guidezpl@users.noreply.github.com Always run coverage upload step, even if a single test fails (flutter/flutter#187614)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC louisehsu@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
creatorpiyush pushed a commit to creatorpiyush/packages that referenced this pull request Jun 10, 2026
…r#11876)

flutter/flutter@1bdf4af...66aaa9a

2026-06-08 katelovett@google.com Add docs on bumping Dart (flutter/flutter#187540)
2026-06-08 rmacnak@google.com Rename Dart_LoadELF2 back to Dart_LoadELF. (flutter/flutter#187677)
2026-06-08 1063596+reidbaker@users.noreply.github.com Add bare, reidbaker, and android agents (flutter/flutter#187588)
2026-06-08 engine-flutter-autoroll@skia.org Roll Dart SDK from 73ec2745c49a to 39f1c44e294f (3 revisions) (flutter/flutter#187684)
2026-06-08 bdero@google.com [Flutter GPU] Document the formats.dart enums (flutter/flutter#187628)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from 0ea3dae686e3 to 43f135735152 (3 revisions) (flutter/flutter#187683)
2026-06-08 bdero@google.com [flutter_tools] Fix `flutter create` crash with SDK packages in bin/cache/pkg (flutter/flutter#187653)
2026-06-08 engine-flutter-autoroll@skia.org Roll Packages from 61bdbb4 to 13b49f4 (1 revision) (flutter/flutter#187678)
2026-06-08 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from fAGotRbStYGA0idum... to KNe93cf5wU4xG2d-m... (flutter/flutter#187675)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from d17c51db4ede to 0ea3dae686e3 (1 revision) (flutter/flutter#187674)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from 9659a87f500f to d17c51db4ede (2 revisions) (flutter/flutter#187672)
2026-06-08 engine-flutter-autoroll@skia.org Roll Skia from a56d5a4e1120 to 9659a87f500f (1 revision) (flutter/flutter#187667)
2026-06-07 engine-flutter-autoroll@skia.org Roll Skia from 101faf7d9d1f to a56d5a4e1120 (1 revision) (flutter/flutter#187665)
2026-06-07 burak.karahan@mail.ru Remove Material import from navigator replacement tests (flutter/flutter#186674)
2026-06-07 burak.karahan@mail.ru Remove Material import from editable text cursor tests (flutter/flutter#186671)
2026-06-07 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from eIU3QDrxaBPAMY9oi... to fAGotRbStYGA0idum... (flutter/flutter#187656)
2026-06-07 engine-flutter-autoroll@skia.org Roll Skia from 294ac0cb2a7d to 101faf7d9d1f (1 revision) (flutter/flutter#187655)
2026-06-06 engine-flutter-autoroll@skia.org Roll Skia from 91ee612cf552 to 294ac0cb2a7d (2 revisions) (flutter/flutter#187651)
2026-06-06 engine-flutter-autoroll@skia.org Roll Skia from a47a9a2c8ae5 to 91ee612cf552 (4 revisions) (flutter/flutter#187642)
2026-06-06 engine-flutter-autoroll@skia.org Roll Fuchsia Linux SDK from N_LiSaBSUsE2LDZgG... to eIU3QDrxaBPAMY9oi... (flutter/flutter#187641)
2026-06-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 05243f181c21 to 73ec2745c49a (2 revisions) (flutter/flutter#187640)
2026-06-06 engine-flutter-autoroll@skia.org Roll Fuchsia GN SDK from oOAcFhkoE2_-Sy67z... to a87CbQSWEjkPUK1ZY... (flutter/flutter#187632)
2026-06-06 engine-flutter-autoroll@skia.org Roll Dart SDK from 6a9a0efe66eb to 05243f181c21 (1 revision) (flutter/flutter#187634)
2026-06-05 bdero@google.com [Flutter GPU] Add instanced draw support (flutter/flutter#187359)
2026-06-05 30870216+gaaclarke@users.noreply.github.com clears out the android context after the frame on mediatek devices (flutter/flutter#187404)
2026-06-05 kevmoo@users.noreply.github.com fix(tool): initialize asset isModified state on startup to prevent 2x hot restart slowdown (flutter/flutter#187488)
2026-06-05 magder@google.com Remove reference to 'good first issue' in the docs (flutter/flutter#187615)
2026-06-05 stuartmorgan@google.com Remove references to 'good first issue' (flutter/flutter#187617)
2026-06-05 154381524+flutteractionsbot@users.noreply.github.com Revert "Add support for stylus buttons" (flutter/flutter#187581)
2026-06-05 6655696+guidezpl@users.noreply.github.com Always run coverage upload step, even if a single test fails (flutter/flutter#187614)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages
Please CC louisehsu@google.com,stuartmorgan@google.com on the revert to ensure that a human
is aware of the problem.

To file a bug in Packages: https://github.com/flutter/flutter/issues/new/choose

To report a problem with the AutoRoller itself, please file a bug:
https://issues.skia.org/issues/new?component=1389291&template=1850622

Documentation for the AutoRoller is here:
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
royarg02 pushed a commit to royarg02/flutter that referenced this pull request Jun 13, 2026
Fixes flutter#187725, regression was introduced in flutter#187488

`DevFSFileContent.isModifiedAfter` returned `true` whenever the cached
`_fileStat` was `null`, ignoring the time argument entirely. `_fileStat`
is the sync baseline written only by `markClean()` the entries of a
freshly built `AssetBundle` are never marked clean, so `_fileStat` is
always `null` for them and `isModifiedAfter` always reported them as
modified.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com>
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
… hot restart slowdown (flutter#187488)

Prior to this fix, the first hot restart would incorrectly detect all
assets as modified and sync/recompile all of them. This was because
DevFS.updateBundle bypassed the asset loop during the initial
application startup, which prevented the stateful isModified getter from
being initialized.

This fix accesses isModified for each asset in the bundle during startup
to initialize the cache, matching the behavior before the asset
processing refactor.

Fixes flutter#187391
via-guy pushed a commit to via-guy/flutter that referenced this pull request Jun 26, 2026
Fixes flutter#187725, regression was introduced in flutter#187488

`DevFSFileContent.isModifiedAfter` returned `true` whenever the cached
`_fileStat` was `null`, ignoring the time argument entirely. `_fileStat`
is the sync baseline written only by `markClean()` the entries of a
freshly built `AssetBundle` are never marked clean, so `_fileStat` is
always `null` for them and `isModifiedAfter` always reported them as
modified.

## Pre-launch Checklist

- [x] I read the [Contributor Guide] and followed the process outlined
there for submitting PRs.
- [x] I read the [AI contribution guidelines] and understand my
responsibilities, or I am not using AI tools.
- [x] I read the [Tree Hygiene] wiki page, which explains my
responsibilities.
- [x] I read and followed the [Flutter Style Guide], including [Features
we expect every widget to implement].
- [x] I signed the [CLA].
- [x] I listed at least one issue that this PR fixes in the description
above.
- [x] I updated/added relevant documentation (doc comments with `///`).
- [x] I added new tests to check the change I am making, or this PR is
[test-exempt].
- [x] I followed the [breaking change policy] and added [Data Driven
Fixes] where supported.
- [x] All existing and new tests are passing.

<!-- Links -->
[Contributor Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview
[AI contribution guidelines]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#ai-contribution-guidelines
[Tree Hygiene]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md
[test-exempt]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests
[Flutter Style Guide]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md
[Features we expect every widget to implement]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement
[CLA]: https://cla.developers.google.com/
[flutter/tests]: https://github.com/flutter/tests
[breaking change policy]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes
[Discord]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md
[Data Driven Fixes]:
https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md

Co-authored-by: Kevin Moore <kevmoo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CICD Run CI/CD tool Affects the "flutter" command-line tool. See also t: labels.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[tool] 2x slowdown in hot restart

3 participants