From 35aa94b223371b6b3bf14e56a2da4445c203ce86 Mon Sep 17 00:00:00 2001 From: ownedbywuigi Date: Fri, 27 Mar 2026 15:23:58 +0000 Subject: [PATCH] Increase image cache size and adjust related parameters for improved performance --- image/VectorImage.cpp | 4 ++-- image/imgLoader.cpp | 44 +++++++++++++++++++++++++++++++++++-- modules/libpref/init/all.js | 12 ++++++---- 3 files changed, 52 insertions(+), 8 deletions(-) diff --git a/image/VectorImage.cpp b/image/VectorImage.cpp index fb56c4b662..d6b66f8160 100644 --- a/image/VectorImage.cpp +++ b/image/VectorImage.cpp @@ -936,9 +936,9 @@ VectorImage::CreateSurfaceAndShow(const SVGDrawingParameters& aParams, BackendTy // are scaled repeatedly (a rather common scenario) that can quickly exhaust // the cache. // Similar to max image size calculations, this has a max cap and size check. - // max cap = 8000 (pixels); size check = 5% of cache + // max cap = 8000 (pixels); size check = 10% of cache int32_t maxDimension = 8000; - int32_t maxCacheElemSize = (gfxPrefs::ImageMemSurfaceCacheMaxSizeKB() * 1024) / 20; + int32_t maxCacheElemSize = (gfxPrefs::ImageMemSurfaceCacheMaxSizeKB() * 1024) / 10; bool bypassCache = bool(aParams.flags & FLAG_BYPASS_SURFACE_CACHE) || // Refuse to cache animated images: diff --git a/image/imgLoader.cpp b/image/imgLoader.cpp index d8e50cb2eb..212bd42da7 100644 --- a/image/imgLoader.cpp +++ b/image/imgLoader.cpp @@ -1048,7 +1048,6 @@ imgLoader::CreateNewProxyForRequest(imgRequest* aRequest, class imgCacheExpirationTracker final : public nsExpirationTracker { - enum { TIMEOUT_SECONDS = 10 }; public: imgCacheExpirationTracker(); @@ -1057,10 +1056,45 @@ protected: }; imgCacheExpirationTracker::imgCacheExpirationTracker() - : nsExpirationTracker(TIMEOUT_SECONDS * 1000, + : nsExpirationTracker( + Preferences::GetUint( + "image.cache.entry_timeout_seconds", + 15) * 1000, "imgCacheExpirationTracker") { } +static bool +ShouldKeepRecentlyUsedAssetInCache(imgCacheEntry* aEntry) +{ + RefPtr request = aEntry->GetRequest(); + if (!request) { + return false; + } + + const char* mimeType = request->GetMimeType(); + if (!mimeType) { + return false; + } + + // Keep small, frequently reused static assets warm a bit longer. + if (!nsCRT::strcmp(mimeType, IMAGE_SVG_XML) || + !nsCRT::strcmp(mimeType, IMAGE_PNG) || + !nsCRT::strcmp(mimeType, IMAGE_WEBP)) { + const uint32_t kMaxWarmAssetBytes = 1024 * 1024; + const uint32_t kRecentUseGraceSeconds = 120; + + if (aEntry->GetDataSize() <= kMaxWarmAssetBytes) { + uint32_t now = SecondsFromPRTime(PR_Now()); + uint32_t touched = aEntry->GetTouchedTime(); + if (now >= touched && (now - touched) <= kRecentUseGraceSeconds) { + return true; + } + } + } + + return false; +} + void imgCacheExpirationTracker::NotifyExpired(imgCacheEntry* entry) { @@ -1068,6 +1102,12 @@ imgCacheExpirationTracker::NotifyExpired(imgCacheEntry* entry) // mechanism doesn't. RefPtr kungFuDeathGrip(entry); + if (ShouldKeepRecentlyUsedAssetInCache(entry)) { + entry->Touch(); + entry->Loader()->VerifyCacheSizes(); + return; + } + if (MOZ_LOG_TEST(gImgLog, LogLevel::Debug)) { RefPtr req = entry->GetRequest(); if (req) { diff --git a/modules/libpref/init/all.js b/modules/libpref/init/all.js index 5f7d02ac62..4a09cecae5 100644 --- a/modules/libpref/init/all.js +++ b/modules/libpref/init/all.js @@ -4275,11 +4275,15 @@ pref("image.animated.decode-on-demand.batch-size", 6); pref("image.animated.resume-from-last-displayed", true); // The maximum size, in bytes, of the decoded images we cache -pref("image.cache.size", 5242880); +pref("image.cache.size", 20971520); // A weight, from 0-1000, to place on time when comparing to size. // Size is given a weight of 1000 - timeweight. -pref("image.cache.timeweight", 500); +pref("image.cache.timeweight", 650); + +// Time in seconds before unproxied entries in the in-memory image cache are +// considered for eviction by the expiration tracker. +pref("image.cache.entry_timeout_seconds", 15); // Decode all images automatically on load, ignoring our normal heuristics. pref("image.decode-immediately.enabled", false); @@ -4326,7 +4330,7 @@ pref("image.mem.decode_bytes_at_a_time", 16384); // Minimum timeout for expiring unused images from the surface cache, in // milliseconds. This controls how long we store cached temporary surfaces. -pref("image.mem.surfacecache.min_expiration_ms", 60000); // 60s +pref("image.mem.surfacecache.min_expiration_ms", 180000); // 180s // Maximum size for the surface cache, in kilobytes. pref("image.mem.surfacecache.max_size_kb", 1048576); // 1GB @@ -4343,7 +4347,7 @@ pref("image.mem.surfacecache.size_factor", 4); // surface cache on memory pressure, a discard factor of 2 means to discard half // of the data, and so forth. The default should be a good balance for desktop // and laptop systems, where we never discard visible images. -pref("image.mem.surfacecache.discard_factor", 1); +pref("image.mem.surfacecache.discard_factor", 2); // How many threads we'll use for multithreaded decoding. If < 0, will be // automatically determined based on the system's number of cores.