Description
TLDR
As soon as number of (mixin applications + files with part
directive + @patch
annotations) exceed ~8000 and number of dart files exceed 16384 gen_snapshot with compressed pointers fails with
Error: Out of memory
Exhausted heap space, trying to allocate <number> bytes.
Description
A few month ago we faced in issue with Out of memory
from gen_snapshot, recently we were finally able to reproduce it in example project without internal code.
It is mainly an issue for flutter, since compressed pointers don't seem to be a thing anywhere except arm64/x86_64 android, but it is caused by implementation of KernelLoader.
Every time KernelLoader is created call to ClassForScriptAt
creates patch_classes_
and they don't seem to be ever cleared during aot compilation.
Steps to reproduce
example with reproduction: example project oom
dart ./tools/generate.dart && flutter build apk --release
(same for --profile
)
- expected result: successful build
- actual result:
Exhausted heap space, trying to allocate 83552 bytes.
Error: Out of memory
Dart snapshot generator failed with exit code 254
Exhausted heap space, trying to allocate 83552 bytes.
Error: Out of memory
Dart snapshot generator failed with exit code 254
Target android_aot_release_android-arm64 failed: Exception: AOT snapshotter exited with code 254
Target android_aot_release_android-x64 failed: Exception: AOT snapshotter exited with code 254
> Task :app:compileFlutterBuildRelease FAILED
(actual number of bytes might be different between versions, but it is consistent on the same version)
- Dart version: 2.19.6, 3.0.0, 3.0.6, 3.2.2, 3.3.0-197.0.dev (basically all the versions up to version used in flutter master channel)
What have we tried to do to mitigate the issue internally
- disable compressed pointers: flutter/engine@3.7.12...2ZeroSix:engine:feature/disable_compresed_pointers
- it does work, but, as expected, it leads to slightly increased memory footprint, not critical, but sensible
- reuse patch classes between KernelLoaders, quick implementation is here: 2.19.6...2ZeroSix:sdk:feature/reuse_patch_classes
- We've settled on this solution for now, it's not perfect, but it works for now without any increase in memory consumption
- ideally it could be tackled down with 1 allocation in aot mode in 3 (as far as i understand it is
platform
,vm_outline
andapp
) allocations in jit mode. Probably it could be shared through the whole isolate(?), the only thing that stopped me from investigating it further is that I do not have enough understanding of what I could broke with it and quick solution was enough to postpone the issue for a quite some time