feat: optimize Flutter codec loading and native Surface lifecycle - #59
q760440238 wants to merge 13 commits into
Conversation
- decode animated WebP resources with GlideWebpDecoder - adapt reusable WebP frame buffers to PowerImage texture rendering - support network, file, Flutter asset, and native asset loaders - modernize the example for current Flutter and Android toolchains
|
YuQian seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account. You have signed the CLA already but the status is still pending? Let us recheck it. |
Draw animated drawables directly to Flutter surfaces, coalesce stale frame invalidations, use hardware canvases when available, migrate textures to SurfaceProducer lifecycle handling, and decode Glide resources at their target size.
|
补充本轮 Android 生命周期与调度优化(commit
最终验证: |
|
最终修复已推送到 commit 本轮先通过 Glide/PowerImage 线程日志确认“多图像排队”不是单线程串行,而是每图 SurfaceProducer 多缓冲与 Huawei VOG-AL10 同场景实测:Total PSS 中位数从 340.2 MB 降到 214.4 MB(-125.8 MB,-37.0%),Native Heap PSS 从 199.8 MB 降到 52.5 MB(-73.7%)。Android 16 模拟器与 验证:Flutter 54/54、fixture 2/2、Gradle 118 tasks;模拟器与 Huawei 真机均完成 20 个不同 animated WebP 的滚动、并发动画和生命周期测试。本次仅改 Android,iOS 未改。 |
根因与证据复核(commit
|
| 库 | Raster avg (ms) | Raster max (ms) | Raster count | Java heap max (KB) | RSS anon max (KB) | RSS file max (KB) | RSS total max (KB) |
|---|---|---|---|---|---|---|---|
| PowerImage | 0.490 | 1.093 | 209 | 5,819 | 88,088 | 277,924 | 366,012 |
| cached_network_image | 0.494 | 1.114 | 207 | 2,521 | 87,612 | 279,204 | 366,816 |
| extended_image | 0.446 | 1.428 | 211 | 2,329 | 88,944 | 275,956 | 364,900 |
客观结论:PowerImage 对 cached_network_image 的 raster avg 快约 0.8%、max 低约 1.9%、总 RSS 低约 0.2%;对 extended_image 的 avg 慢约 9.9%,但 max 低约 23.5%,总 RSS 高约 0.3%。三者总 RSS 基本同档;PowerImage 因 Glide 额外持有约 3.2 MiB Java heap,不能宣称所有指标全面领先,当前优势是最小 raster 峰值和更完整的原生 Drawable/Surface 生命周期能力。
验证:根库 Flutter 55/55、example 3/3(20 个文件编码、首帧和动画属性均不同,页面卸载后无 setState 异常)、Gradle 132 tasks BUILD SUCCESSFUL;API 36 模拟器 PowerImage 5/5,Huawei 真机三库 15/15。本次仍只改 Android 路径,iOS 未改。
最终合并回归修复(commit
|
Added a benchmark report comparing the performance of 20 different GIPHY animations in WebP format on a Huawei VOG-AL10 device. The report includes test environment details, results, and conclusions regarding CPU and memory usage.
Added a CSV file containing Giphy materials with metadata including dimensions, frame count, duration, and URLs.
Additional verification: 20-animation steady-state benchmarkThe head branch now includes the raw result, report, and material manifest. This is additive to the existing cold first-frame comparison in the PR body (PowerImage 41.967/46.382 ms P50/P95; ExtendedImage 10.1.0 42.390/63.427 ms; CachedNetworkImage 3.4.1 75.667/78.328 ms). Huawei VOG-AL10, Android 10/API 29, 20 different GIPHY animated WebPs shown simultaneously in a fixed 4x5 grid. Five interleaved rounds per implementation, with 12 s warm-up and 20 s sampling per round:
PowerImage and ExtendedImage are effectively tied on median CPU. PowerImage's median PSS is 1.71% higher, but P95 PSS is 2.22% lower, P95 RSS is 3.36% lower, and P95 Graphics is 9.04% lower. Versus native Glide, PowerImage uses 3.17% less median CPU and 11.93% less P95 CPU, while Flutter Engine/Impeller adds about 38 MiB PSS. All 300 GPU-frequency samples remained at 139 MHz (720 MHz maximum). GPU utilization/perf counters are not accessible on this production kernel, so frequency is a workload proxy only. Full report and machine-readable results: |
Closes #61.
Summary
This updates PowerImage's ordinary-image path and native Surface lifecycle while preserving explicit native/custom decoder support.
ImageProvider+ Flutter codec for ordinary HTTP PNG/GIF/WebP by default; native remains opt-in for custom Drawable/private decoders;ImmutableBuffer.fromFilePath;Codec.getNextFrame()only; later animated frames remain normal asynchronous Flutter codec calls;PowerImage.networkwidget through Flutter's standardImagepath while keeping the previousFilterQuality.lowsemantics;waitForPresentwith a teardown fence;PowerImageBinding/ImageCacheExtbehavior;Physical-device results
Huawei VOG-AL10, Android 10 / API 29, Flutter 3.38.7, full AOT, identical in-process loopback fixture, 160x160 target. ExtendedImage is pinned to 10.1.0, CachedNetworkImage to 3.4.1. P95 is nearest-rank.
ImmutableBuffer.fromFilePathgetNextFrame()ImagewidgetqueueBufferaverageThe animated frame-count median increased from 819 to 826; private RSS remained flat. Rejected concurrency/quality experiments are not part of the final result set.
Final cache/lifecycle scenarios:
Full methodology and raw AndroidX JSON:
https://github.com/q760440238/power_image/tree/feature/android-animated-webp/example/android/macrobenchmark/results/2026-08-03-VOG-AL10
Verification
flutter analyze— no errors (repository's existing warnings/info remain)flutter test— 83 passedexample/flutter test— 3 passed./gradlew :power_image:testDebugUnitTest :app:testDebugUnitTest— passed