Repository navigation
Description
Use case
We maintain a custom Flutter embedder on a Linux-based embedded platform and have observed a significant increase in GPU memory consumption and rasterisation cost when using Impeller EGL compared to SKIA EGL.
Our application contains complex UI effects, including blur filters. During rapid scrolling, GPU memory usage can increase substantially. Investigation of the engine identified RenderTargetCache and its keep_alive_frame_count configuration as a major contributor to resource usage.
By locally modifying the engine and reducing keep_alive_frame_count from the default value of 4 to 1 or 0, we observed significant reductions in peak GPU memory consumption. In complex blur animation scenarios, lowering the value to 1 or 0 also resulted in approximately 80% lower rasterisation time on our platform.
Different platforms have different memory, GPU and rendering constraints, and the current hardcoded value does not allow embedders to tune this behaviour for their specific hardware characteristics.
We are not aware of any existing Flutter package that can provide this functionality, as the setting exists within the engine and is not currently exposed through a public configuration interface.
Proposal
Expose Impeller's keep_alive_frame_count as a configurable engine/embedding parameter rather than a hardcoded value.
This would allow platform embedders to tune render target cache retention based on the capabilities and constraints of their target hardware. For example, embedded and memory-constrained devices may prefer lower values to reduce GPU memory usage and rasterisation overhead, while more capable devices could continue using the current default.
Ideally this could be configured through embedder settings or a launch-time engine argument.
engine/src/flutter/impeller/entity/render_target_cache.h
explicit RenderTargetCache(std::shared_ptr<Allocator> allocator, uint32_t keep_alive_frame_count = 4);
Activity
loic-sharma commentedon Aug 5, 2026
@luke-willi Thanks for creating this issue! Before we expose new configuration options, we'd like to investigate if we make Impeller more memory efficient in this scenario. Could you provide a minimal app that reproduces this on the latest Flutter Android or Flutter Linux?
To reproduce this issue on Flutter Android or Flutter Linux, these steps might be useful:
Switch to the latest Flutter main channel:
If using Flutter Android: configure it to use Impeller's OpenGLES backend by modifying the app's
android/app/src/main/AndroidManifest.xmlfile and adding the following content in the<application>tag:Run the app in profile mode:
Verify you see this console line:
If using Flutter Android: you can use Android Studio's profiler to check the app's memory usage over time.
gaaclarke commentedon Aug 10, 2026
I'm hesitant to expose this value, it's a tuning value for an internal heuristic on how we clear out memory. If we expose it, it will tie our hands about the heuristics we are using. If you are building for custom embedders, don't you have an opportunity to tweak it yourself inside the source code?
loic-sharma commentedon Aug 11, 2026
I agree we'd prefer not to expose this config if possible. The preferred solution would be for us to add optimizations for this scenario, and we'll need a minimal repro for that.
@gaaclarke We recommend against creating custom patches on the Flutter engine, where possible. This makes it harder to keep custom embedders up-to-date.
gaaclarke commentedon Aug 11, 2026
In the case where you are just changing constants, it shouldn't be difficult at all. We could make that even easier by percolating build constants to a config file so someones build environment could easily change them. I'm not sure if that's worth the effort though.
gaaclarke commentedon Aug 11, 2026
I mean embedder's are building their own engine, they could easily insert a script with a regex that switches the constant.
luke-willi commentedon Aug 17, 2026
/@loic-sharma To test this we have been using an extreme case, an app that cycles through six full-screen, differently-colored Gaussian-blurred "pill" pages.
main.dart
blur.dart
I ran this test using flutter drive, and measured the rasterisation time and GPU memory on a physical Android device - Samsung Galaxy S24+ (SM-S926B). Results were as followed:
Rasterizer time (ms)
GPU memory (dumpsys meminfo Graphics PSS, KB)
gaaclarke commentedon Sep 18, 2026
@luke-willi thanks for the reproduction. Some thoughts.
The reproduction is executed on an android device. It's important to note the issue is now saying it's reproducible on multiple devices whereas the original description framed this as something unique to a particular hardware.
The reproduction is showing us good movement in numbers, but it is still a contrived benchmark so we have to be careful about accommodating it too much. It is informed by your real world usage too though.
I think there is good evidence here that there may be an improvement that can be made that benefits all (or most) flutter developers. We should explore that avenue. Having a hidden flag benefits few users. We really don't want to be in a position where people have to tweak hyper parameters to get optimal performance from Flutter.
Can you clarify if keep_alive_frame_count=0 is your requirement? That is mentioned in the description but the repro shows benchmarks for keep_alive_frame_count=1.
As a next step I'd like to see the benchmark results for standard Flutter usage with keep_alive_frame_count=1 ( example: https://flutter-flutter-perf.luci.app/e/?begin=1789666314&enable_chart_tooltip=true&end=1789752714&plotSummary=true&queries=sub_result%3Daverage_gpu_memory_mb%26sub_result%3Daverage_frame_rasterizer_time_millis%26test%3Dnew_gallery_impeller__transition_perf&use_titles=true )
We might be able to just change that with proper evidence in-hand. I wasn't around for the selection of 4, so I'm not sure what went into that decision. We should do some git archeology there.
gaaclarke commentedon Sep 18, 2026
P1 for investigation of standard performance benchmarks with
keep_alive_frame_count=1and archeology intokeep_alive_frame_count=4.11 remaining items
[-]Configuration of Impeller EGL keep_alive_frame_count[/-][+][Impeller] Make the render target cache configurable[/+][avio] RenderTargetCache complete keys and miss telemetry
[avio] RenderTargetCache ages once per raster frame
mk-towers commentedon Oct 5, 2026
@gaaclarke Thanks for investigating this.
We performed some additional testing on Android across a couple of physical devices and the Android emulator. We are consistently seeing lower graphics memory usage with KAFC=0 and KAFC=1 versus KAFC=4 but, consistent with your results, we don't see a consistent impact on rasterizer time. Possibly the rasterizer time difference noted above is device-specific.
I tested #193027 (cherry-picked to 3.47.5) on one of our embedded Linux devices and it works well:
If #193027 is merged, are you planning to keep cache_budget_bytes as an internal value or expose it?
gaaclarke commentedon Oct 5, 2026
@mk-towers thanks for testing it out. What differences were you seeing in memory? My tests just showed a 5 MB different in the peak usage. I'm uncertain if that is a change worth accepting the extra complexity over.
I'm not going to preemptively expose flags without any evidence that it's required.
mk-towers commentedon Oct 7, 2026
@gaaclarke I've done some additional testing and the results are very inconsistent. I think we need a better test case that's more consistent and representative of real-world usage. I'll work on one and share the results.
github-actions commentedon Oct 12, 2026
Without additional information, we are unfortunately not sure how to resolve this issue. We are therefore reluctantly going to close this bug for now.
If you find this problem please file a new issue with the same description, what happens, logs and the output of 'flutter doctor -v'. All system setups can be slightly different so it's always better to open new issues and reference the related ones.
Thanks for your contribution.
loic-sharma commentedon Oct 12, 2026
@mk-towers Our bot closed this issue because the original reporter, @luke-willi, hasn't replied in 3 weeks. Once you have a better test case, could you file a new issue? Please cc @gaaclarke and I on that new issue once it's ready :)
github-actions commentedon Oct 26, 2026
This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of
flutter doctor -vand a minimal reproduction of the issue.