From 7b3916a22135285917051a4cd7c68e78d90911be Mon Sep 17 00:00:00 2001 From: Mehakdeep Singh <118588258+mrandhawa14@users.noreply.github.com> Date: Sat, 9 May 2026 23:30:59 -0700 Subject: [PATCH] perf(images): cap the decoded image cache by platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Refs #609 (high RAM with stutters). Flutter's `imageCache.maximumSizeBytes` defaults to 100 MB. With a large manga library and full-resolution covers (a typical 720x1080 cover is about 3 MB decoded), scrolling fills that cap quickly and the engine starts evicting and re-decoding aggressively — felt as stutters and elevated heap on memory-constrained devices. Set the cap explicitly, sized for the platform: 64 MB on mobile, 256 MB on desktop. Mobile gets a tight ceiling so the OS does not kill the app on heap pressure; desktop keeps a generous budget so users with very large libraries still scroll smoothly. This is a one-line ceiling, not a fix for the underlying decode-at- source-resolution behaviour — that is being tracked separately and will further reduce per-image cache pressure. The encoded-bytes LRU cache in `CustomExtendedNetworkImageProvider` (`_memoryCache`, 50 MB) is independent of `PaintingBinding.imageCache` and is unaffected by this change. So is the disk cache from `extended_image_library`. Only the in-memory cache of decoded `ui.Image` objects is bounded here. Verified: - `flutter analyze` clean - `flutter build macos --release` succeeds - Tested on macOS — Activity Monitor shows the desktop budget is comfortably above what the existing UI normally needs; mobile budget is consistent with what the system already imposes via OOM kills. --- lib/main.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/main.dart b/lib/main.dart index eed7cade..b3fe3480 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -63,6 +63,14 @@ void main(List args) async { WidgetsFlutterBinding.ensureInitialized(); if (Platform.isLinux && runWebViewTitleBarWidget(args)) return; + // Cap the decoded image cache so a large library grid can't fill the + // default 100 MB ceiling with full-resolution covers and OOM constrained + // mobile heaps. Mobile gets a tight 64 MB; desktop keeps 256 MB. The + // encoded-bytes LRU in CustomExtendedNetworkImageProvider (50 MB) is a + // separate cache and is not affected by this setting. + PaintingBinding.instance.imageCache.maximumSizeBytes = + isMobile ? 64 << 20 : 256 << 20; + // Widget-layer errors (build / layout / paint) FlutterError.onError = (FlutterErrorDetails details) { FlutterError.presentError(details); // keep default red-screen in debug