From d370c7e40c26f9ef826899f91ecd9730fdf766af Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 14 May 2026 20:51:05 +0000 Subject: [PATCH] perf(images): coalesce duplicate in-flight Coil network requests Switch the three image NetworkFetcher sites from ConcurrentRequestStrategy.UNCOORDINATED to DeDupeConcurrentRequestStrategy, Coil's coordinated default. UNCOORDINATED let every request hit the network independently, so the same avatar across many visible feed notes became N parallel downloads competing for the per-host dispatcher slots and queueing the genuinely distinct images behind them. The de-duping strategy lets concurrent requests for a URL share the first download and then read from disk. https://claude.ai/code/session_01BeWZGTz48kzURQLTYyN5x9 --- .../vitorpamplona/amethyst/service/images/BlossomFetcher.kt | 4 ++-- .../vitorpamplona/amethyst/service/images/ImageLoaderSetup.kt | 4 ++-- .../amethyst/service/images/ProfilePictureFetcher.kt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/BlossomFetcher.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/BlossomFetcher.kt index 7406c8e13..38b7b4577 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/BlossomFetcher.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/BlossomFetcher.kt @@ -27,8 +27,8 @@ import coil3.annotation.ExperimentalCoilApi import coil3.fetch.FetchResult import coil3.fetch.Fetcher import coil3.network.CacheStrategy -import coil3.network.ConcurrentRequestStrategy import coil3.network.ConnectivityChecker +import coil3.network.DeDupeConcurrentRequestStrategy import coil3.network.NetworkFetcher import coil3.network.okhttp.asNetworkClient import coil3.request.Options @@ -74,7 +74,7 @@ class BlossomFetcher( diskCache = lazy { imageLoader.diskCache }, cacheStrategy = lazy { CacheStrategy.DEFAULT }, connectivityChecker = lazy { connectivityCheckerLazy.get(options.context) }, - concurrentRequestStrategy = lazy { ConcurrentRequestStrategy.UNCOORDINATED }, + concurrentRequestStrategy = lazy { DeDupeConcurrentRequestStrategy() }, ) } } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ImageLoaderSetup.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ImageLoaderSetup.kt index f7b25bee4..da4d6829c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ImageLoaderSetup.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ImageLoaderSetup.kt @@ -33,8 +33,8 @@ import coil3.gif.AnimatedImageDecoder import coil3.gif.GifDecoder import coil3.memory.MemoryCache import coil3.network.CacheStrategy -import coil3.network.ConcurrentRequestStrategy import coil3.network.ConnectivityChecker +import coil3.network.DeDupeConcurrentRequestStrategy import coil3.network.NetworkFetcher import coil3.network.okhttp.asNetworkClient import coil3.request.Options @@ -149,7 +149,7 @@ class OkHttpFactory( diskCache = lazy { imageLoader.diskCache }, cacheStrategy = cacheStrategyLazy, connectivityChecker = lazy { connectivityCheckerLazy.get(options.context) }, - concurrentRequestStrategy = lazy { ConcurrentRequestStrategy.UNCOORDINATED }, + concurrentRequestStrategy = lazy { DeDupeConcurrentRequestStrategy() }, ) } diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ProfilePictureFetcher.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ProfilePictureFetcher.kt index 0f85b5926..c0ff86858 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ProfilePictureFetcher.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/service/images/ProfilePictureFetcher.kt @@ -30,8 +30,8 @@ import coil3.fetch.Fetcher import coil3.fetch.ImageFetchResult import coil3.key.Keyer import coil3.network.CacheStrategy -import coil3.network.ConcurrentRequestStrategy import coil3.network.ConnectivityChecker +import coil3.network.DeDupeConcurrentRequestStrategy import coil3.network.NetworkFetcher import coil3.network.okhttp.asNetworkClient import coil3.request.Options @@ -113,7 +113,7 @@ class ProfilePictureFetcher( diskCache = diskCacheLazy, cacheStrategy = lazy { CacheStrategy.DEFAULT }, connectivityChecker = lazy { connectivityCheckerLazy.get(options.context) }, - concurrentRequestStrategy = lazy { ConcurrentRequestStrategy.UNCOORDINATED }, + concurrentRequestStrategy = lazy { DeDupeConcurrentRequestStrategy() }, ) return ProfilePictureFetcher(