sdk
sdk copied to clipboard
Mixins, part files and @patches are triggering OOM in gen_snapshot with compressed pointers
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: https://github.com/flutter/engine/compare/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: https://github.com/dart-lang/sdk/compare/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
// @2ZeroSix thanks for the detailed reproduction instructions we will investigate.
// @alexmarkov @rmacnak-google
@2ZeroSix please make sure to include some valid open source license (MIT, GPL, BSD, etc) into your repo. thanks.
@2ZeroSix please make sure to include some valid open source license (MIT, GPL, BSD, etc) into your repo. thanks.
done
@2ZeroSix a fix went in at top of tree for this issue and the example reproduction you provided works, can you try your real application at top of tree and see if you are still running into the same issue.
@2ZeroSix a fix went in at top of tree for this issue and the example reproduction you provided works, can you try your real application at top of tree and see if you are still running into the same issue.
@a-siva I have replaced our current work-around with 448b9ef989ae4669f7a34f17019d05e0fc7e389a and it has worked flawlessly. Thank you!
I'll try to replace it in main and see if we'll found any issues with that.