EGL Multifile BlobCache: Limit entry count
Limit the number of entries to 4096.
This is an empirical number based on app behavior. Some using many
small entries are taking a long time to load the cache.
Test: MultifileBlobCacheTest.CacheMaxEntrySucceeds
Bug: b/295051628
Bug: b/310535559
Change-Id: Ibc671cec25dd7c9bc10b9d1ee1fb837180eb7551
diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp
index ed3c616..13a5e7b 100644
--- a/opengl/libs/EGL/MultifileBlobCache.cpp
+++ b/opengl/libs/EGL/MultifileBlobCache.cpp
@@ -62,12 +62,14 @@
namespace android {
MultifileBlobCache::MultifileBlobCache(size_t maxKeySize, size_t maxValueSize, size_t maxTotalSize,
- const std::string& baseDir)
+ size_t maxTotalEntries, const std::string& baseDir)
: mInitialized(false),
mMaxKeySize(maxKeySize),
mMaxValueSize(maxValueSize),
mMaxTotalSize(maxTotalSize),
+ mMaxTotalEntries(maxTotalEntries),
mTotalCacheSize(0),
+ mTotalCacheEntries(0),
mHotCacheLimit(0),
mHotCacheSize(0),
mWorkerThreadIdle(true) {
@@ -270,7 +272,7 @@
size_t fileSize = sizeof(MultifileHeader) + keySize + valueSize;
// If we're going to be over the cache limit, kick off a trim to clear space
- if (getTotalSize() + fileSize > mMaxTotalSize) {
+ if (getTotalSize() + fileSize > mMaxTotalSize || getTotalEntries() + 1 > mMaxTotalEntries) {
ALOGV("SET: Cache is full, calling trimCache to clear space");
trimCache();
}
@@ -485,10 +487,12 @@
void MultifileBlobCache::increaseTotalCacheSize(size_t fileSize) {
mTotalCacheSize += fileSize;
+ mTotalCacheEntries++;
}
void MultifileBlobCache::decreaseTotalCacheSize(size_t fileSize) {
mTotalCacheSize -= fileSize;
+ mTotalCacheEntries--;
}
bool MultifileBlobCache::addToHotCache(uint32_t newEntryHash, int newFd, uint8_t* newEntryBuffer,
@@ -557,7 +561,7 @@
return false;
}
-bool MultifileBlobCache::applyLRU(size_t cacheLimit) {
+bool MultifileBlobCache::applyLRU(size_t cacheSizeLimit, size_t cacheEntryLimit) {
// Walk through our map of sorted last access times and remove files until under the limit
for (auto cacheEntryIter = mEntryStats.begin(); cacheEntryIter != mEntryStats.end();) {
uint32_t entryHash = cacheEntryIter->first;
@@ -590,9 +594,10 @@
// See if it has been reduced enough
size_t totalCacheSize = getTotalSize();
- if (totalCacheSize <= cacheLimit) {
+ size_t totalCacheEntries = getTotalEntries();
+ if (totalCacheSize <= cacheSizeLimit && totalCacheEntries <= cacheEntryLimit) {
// Success
- ALOGV("LRU: Reduced cache to %zu", totalCacheSize);
+ ALOGV("LRU: Reduced cache to size %zu entries %zu", totalCacheSize, totalCacheEntries);
return true;
}
}
@@ -603,6 +608,7 @@
// When removing files, what fraction of the overall limit should be reached when removing files
// A divisor of two will decrease the cache to 50%, four to 25% and so on
+// We use the same limit to manage size and entry count
constexpr uint32_t kCacheLimitDivisor = 2;
// Calculate the cache size and remove old entries until under the limit
@@ -611,8 +617,9 @@
ALOGV("TRIM: Waiting for work to complete.");
waitForWorkComplete();
- ALOGV("TRIM: Reducing multifile cache size to %zu", mMaxTotalSize / kCacheLimitDivisor);
- if (!applyLRU(mMaxTotalSize / kCacheLimitDivisor)) {
+ ALOGV("TRIM: Reducing multifile cache size to %zu, entries %zu",
+ mMaxTotalSize / kCacheLimitDivisor, mMaxTotalEntries / kCacheLimitDivisor);
+ if (!applyLRU(mMaxTotalSize / kCacheLimitDivisor, mMaxTotalEntries / kCacheLimitDivisor)) {
ALOGE("Error when clearing multifile shader cache");
return;
}