Reland "EGL BlobCache: Support multifile cache and flexible size limit"
This reverts commit 82a9353d96954edd78d5e2f342a669dd8ddce5d1 and
incorporates a change to only use the fixed upper cache limit instead
of reading one from GraphicsEnvironment.
Test: Multiple apps and ANGLE traces
Test: atest CtsSdkSandboxInprocessTests
Test: /data/nativetest64/EGL_test/EGL_test
Bug: b/246966894
Change-Id: Iae44e06377de48fe2101bf547b02d3aaf37443d9
diff --git a/opengl/libs/EGL/egl_cache.cpp b/opengl/libs/EGL/egl_cache.cpp
index 8348d6c..6225c26 100644
--- a/opengl/libs/EGL/egl_cache.cpp
+++ b/opengl/libs/EGL/egl_cache.cpp
@@ -16,6 +16,8 @@
#include "egl_cache.h"
+#include <android-base/properties.h>
+#include <inttypes.h>
#include <log/log.h>
#include <private/EGL/cache.h>
#include <unistd.h>
@@ -23,16 +25,23 @@
#include <thread>
#include "../egl_impl.h"
+#include "egl_cache_multifile.h"
#include "egl_display.h"
-// Cache size limits.
+// Monolithic cache size limits.
static const size_t maxKeySize = 12 * 1024;
static const size_t maxValueSize = 64 * 1024;
static const size_t maxTotalSize = 32 * 1024 * 1024;
-// The time in seconds to wait before saving newly inserted cache entries.
+// The time in seconds to wait before saving newly inserted monolithic cache entries.
static const unsigned int deferredSaveDelay = 4;
+// Multifile cache size limit
+constexpr size_t kMultifileCacheByteLimit = 64 * 1024 * 1024;
+
+// Delay before cleaning up multifile cache entries
+static const unsigned int deferredMultifileCleanupDelaySeconds = 1;
+
namespace android {
#define BC_EXT_STR "EGL_ANDROID_blob_cache"
@@ -58,7 +67,8 @@
//
// egl_cache_t definition
//
-egl_cache_t::egl_cache_t() : mInitialized(false) {}
+egl_cache_t::egl_cache_t()
+ : mInitialized(false), mMultifileMode(true), mCacheByteLimit(maxTotalSize) {}
egl_cache_t::~egl_cache_t() {}
@@ -101,6 +111,18 @@
}
}
+ mMultifileMode = true;
+
+ // Allow forcing monolithic cache for debug purposes
+ if (base::GetProperty("debug.egl.blobcache.multifilemode", "") == "false") {
+ ALOGD("Forcing monolithic cache due to debug.egl.blobcache.multifilemode == \"false\"");
+ mMultifileMode = false;
+ }
+
+ if (mMultifileMode) {
+ mCacheByteLimit = kMultifileCacheByteLimit;
+ }
+
mInitialized = true;
}
@@ -110,6 +132,11 @@
mBlobCache->writeToFile();
}
mBlobCache = nullptr;
+ if (mMultifileMode) {
+ checkMultifileCacheSize(mCacheByteLimit);
+ }
+ mMultifileMode = false;
+ mInitialized = false;
}
void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, const void* value,
@@ -122,20 +149,37 @@
}
if (mInitialized) {
- BlobCache* bc = getBlobCacheLocked();
- bc->set(key, keySize, value, valueSize);
+ if (mMultifileMode) {
+ setBlobMultifile(key, keySize, value, valueSize, mFilename);
- if (!mSavePending) {
- mSavePending = true;
- std::thread deferredSaveThread([this]() {
- sleep(deferredSaveDelay);
- std::lock_guard<std::mutex> lock(mMutex);
- if (mInitialized && mBlobCache) {
- mBlobCache->writeToFile();
- }
- mSavePending = false;
- });
- deferredSaveThread.detach();
+ if (!mMultifileCleanupPending) {
+ mMultifileCleanupPending = true;
+ // Kick off a thread to cull cache files below limit
+ std::thread deferredMultifileCleanupThread([this]() {
+ sleep(deferredMultifileCleanupDelaySeconds);
+ std::lock_guard<std::mutex> lock(mMutex);
+ // Check the size of cache and remove entries to stay under limit
+ checkMultifileCacheSize(mCacheByteLimit);
+ mMultifileCleanupPending = false;
+ });
+ deferredMultifileCleanupThread.detach();
+ }
+ } else {
+ BlobCache* bc = getBlobCacheLocked();
+ bc->set(key, keySize, value, valueSize);
+
+ if (!mSavePending) {
+ mSavePending = true;
+ std::thread deferredSaveThread([this]() {
+ sleep(deferredSaveDelay);
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mInitialized && mBlobCache) {
+ mBlobCache->writeToFile();
+ }
+ mSavePending = false;
+ });
+ deferredSaveThread.detach();
+ }
}
}
}
@@ -145,13 +189,17 @@
std::lock_guard<std::mutex> lock(mMutex);
if (keySize < 0 || valueSize < 0) {
- ALOGW("EGL_ANDROID_blob_cache set: negative sizes are not allowed");
+ ALOGW("EGL_ANDROID_blob_cache get: negative sizes are not allowed");
return 0;
}
if (mInitialized) {
- BlobCache* bc = getBlobCacheLocked();
- return bc->get(key, keySize, value, valueSize);
+ if (mMultifileMode) {
+ return getBlobMultifile(key, keySize, value, valueSize, mFilename);
+ } else {
+ BlobCache* bc = getBlobCacheLocked();
+ return bc->get(key, keySize, value, valueSize);
+ }
}
return 0;
}
@@ -161,9 +209,34 @@
mFilename = filename;
}
+void egl_cache_t::setCacheLimit(int64_t cacheByteLimit) {
+ std::lock_guard<std::mutex> lock(mMutex);
+
+ if (!mMultifileMode) {
+ // If we're not in multifile mode, ensure the cache limit is only being lowered,
+ // not increasing above the hard coded platform limit
+ if (cacheByteLimit > maxTotalSize) {
+ return;
+ }
+ }
+
+ mCacheByteLimit = cacheByteLimit;
+}
+
+size_t egl_cache_t::getCacheSize() {
+ std::lock_guard<std::mutex> lock(mMutex);
+ if (mMultifileMode) {
+ return getMultifileCacheSize();
+ }
+ if (mBlobCache) {
+ return mBlobCache->getSize();
+ }
+ return 0;
+}
+
BlobCache* egl_cache_t::getBlobCacheLocked() {
if (mBlobCache == nullptr) {
- mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, maxTotalSize, mFilename));
+ mBlobCache.reset(new FileBlobCache(maxKeySize, maxValueSize, mCacheByteLimit, mFilename));
}
return mBlobCache.get();
}