Repository navigation
Consider disabling picture complexity based raster caching in Skia backend. #131206
Description
The Flutter engine will attempt to estimate the "cost" of the pictures that it renders. When this cost exceeds a threshold and the picture itself is stable, the engine will create a "raster cache" entry for that picture. The raster cache essentially replace the display/canvas operations with a texture containing the rasterized elements which will be reused on subsequent frames. The idea being that this will be cheaper and lead to more performant applications.
There are a few serious problems with the current raster cache complexity based scoring:
- Failure to measure tradeoffs
The benchmarking infrastructure was designed to capture the cost of the cache removing the raster ops on the devices CPU. It did not measure the potentially increased GPU load from texture sampling/loading from video memory. From some local investigations, texture sampling can be multiple times slower than executing the original shaders.
There is also an additional memory cost to holding these raster images. They are only stored in native resolution and can add severals 10s of MB to video memory usages.
- Unpredictable performance
Sometimes developers will inadvertantly create extremely expensive pictures, perhaps by doing something like emulating a paint application with stacked drawing + clears. The performance of this application will likely ping pong between smooth (as hundreds of draw ops are replaced with a texture) to janky once a new drawing operation is appended. This performance is likely to be less intuitive than if we were consistently slow. At least then they might look to developing their own caching strategy that didn't pingpong.
- Unmaintainable herustics
The herustics used to populate the complexity scoring mechanism were developed by a never productionized one time script. From investigation, we know that several of these metrics are likely wrong. For example, there is no advantage to replacing large text blobs with a raster cache entry, as the text blobs are already drawn from sampled textures.
Because of these issues, we've previously decided not to port the raster cache to Impeller. This issue considers the case of also removing this from the Skia backend.
Experimental results
On Friday July 21, I disabled the picture complexity based raster cache heuristics in the engine. There were really only two benchmark changes of note:
- The complex layout scroll perf 90% time regressed by 2.5 MS
- The worst frame time of the textfield perf microbenchmark improved by 325ms
Activity
jonahwilliams commentedon Jul 24, 2023
For the benchmark that regressed, I looked at GPU captures from current ToT (no raster caching) and last stable (with raster caching)
Stable
ToT
Without raster caching the GPU workload is faster and uses less memory.
However raster times did increase, notably because we are spending a bit more time in Skia canvas dispatching per frame.
[-]Disable picutre complexity based raster caching in Skia backend.[/-][+]Consider disabling picture complexity based raster caching in Skia backend.[/+]dnfield commentedon Jul 26, 2023
What's the numeric difference between GPU time/CPU time with and without? It looks like with this change we're saving >1ms of GPU time per frame but we lost ~2.5ms on CPU time?
jonahwilliams commentedon Jul 26, 2023
On the complex layout benchmark, yes
on the gallery benchmarks there was no change
on the textfield benchmark, there was a 250ms+ improvement (because the heuristics don't measure tradeoff costs and are just wrong sometime)
dnfield commentedon Jul 26, 2023
...this seems like a good reason to disable it? Although it'd be good to understand what's going on in the complex layout benchmark more fully, and good to see if we can somehow get measurments of GPU time in our tests.
jonahwilliams commentedon Jul 26, 2023
unfortunately the complex layout benchmark is just ... slow to encode in the SkPicture. So reducing the number of commands helps, disproportionately :(
dnfield commentedon Jul 26, 2023
Is it because there's a large number of commands? Or because there are particularly expensive ones?
We went from a heuristic that was super simple and probably not right, to one that was very complicated and definitely not right.
Should we be measuring the time it takes to encode the SkPicture and go from there?
flutter-triage-bot commentedon Feb 21, 2024
This issue is marked P1 but has had no recent status updates.
The P1 label indicates high-priority issues that are at the top of the work list. This is the highest priority level a bug can have if it isn't affecting a top-tier customer or breaking the build. Bugs marked P1 are generally actively being worked on unless the assignee is dealing with a P0 bug (or another P1 bug). Issues at this level should be resolved in a matter of months and should have monthly updates on GitHub.
Please consider where this bug really falls in our current priorities, and label it or assign it accordingly. This allows people to have a clearer picture of what work is actually planned. Thanks!
jonahwilliams commentedon Feb 26, 2024
I don't think we're going to have time to work on this. We should remove the complexity scoring when we turn on Impeller.
github-actions commentedon Mar 11, 2024
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.