diff options
author | 2024-11-21 19:50:08 -0700 | |
---|---|---|
committer | 2024-11-28 17:00:06 -0700 | |
commit | 96fa0e7723639d173a56379f33e911daef493782 (patch) | |
tree | b37937b027ca2ffcab57c74f75fce07797e92f53 /opengl | |
parent | b7f342a05123a5ff7a1957859710d106d38b347e (diff) |
EGL Multifile Blobcache: Remove entries when valueSize is zero
When set is called with a value size of zero, the cache will simply remove
the entry from disk and return.
Any pending writes will complete before the entry is removed.
Additional tests:
* ZeroSizeRemovesEntry
Based on work by: Igor Nazarov <i.nazarov@samsung.com>
Test: libEGL_test, EGL_test, ANGLE trace tests, apps
Bug: b/355259618, b/380483358
Flag: com.android.graphics.egl.flags.multifile_blobcache_advanced_usage
Change-Id: I092a0e41c587ac036311b5e08e8b6ffa59588bca
Diffstat (limited to 'opengl')
-rw-r--r-- | opengl/libs/EGL/MultifileBlobCache.cpp | 15 | ||||
-rw-r--r-- | opengl/libs/EGL/MultifileBlobCache_test.cpp | 57 |
2 files changed, 70 insertions, 2 deletions
diff --git a/opengl/libs/EGL/MultifileBlobCache.cpp b/opengl/libs/EGL/MultifileBlobCache.cpp index 1f6d4d04e7..04c525e93d 100644 --- a/opengl/libs/EGL/MultifileBlobCache.cpp +++ b/opengl/libs/EGL/MultifileBlobCache.cpp @@ -330,6 +330,8 @@ void MultifileBlobCache::set(const void* key, EGLsizeiANDROID keySize, const voi // Generate a hash of the key and use it to track this entry uint32_t entryHash = android::JenkinsHashMixBytes(0, static_cast<const uint8_t*>(key), keySize); + std::string fullPath = mMultifileDirName + "/" + std::to_string(entryHash); + // See if we already have this file if (flags::multifile_blobcache_advanced_usage() && contains(entryHash)) { // Remove previous entry from hot cache @@ -337,6 +339,17 @@ void MultifileBlobCache::set(const void* key, EGLsizeiANDROID keySize, const voi // Remove previous entry and update the overall cache size removeEntry(entryHash); + + // If valueSize is zero, this is an indication that the user wants to remove the entry from + // cache It has already been removed from tracking, now remove it from disk It is safe to do + // this immediately because we drained the write queue in removeFromHotCache + if (valueSize == 0) { + ALOGV("SET: Zero size detected for existing entry, removing %u from cache", entryHash); + if (remove(fullPath.c_str()) != 0) { + ALOGW("SET: Error removing %s: %s", fullPath.c_str(), std::strerror(errno)); + } + return; + } } size_t fileSize = sizeof(MultifileHeader) + keySize + valueSize; @@ -361,8 +374,6 @@ void MultifileBlobCache::set(const void* key, EGLsizeiANDROID keySize, const voi memcpy(static_cast<void*>(buffer + sizeof(MultifileHeader) + keySize), static_cast<const void*>(value), valueSize); - std::string fullPath = mMultifileDirName + "/" + std::to_string(entryHash); - // Track the size and access time for quick recall and update the overall cache size struct timespec time = {0, 0}; if (flags::multifile_blobcache_advanced_usage()) { diff --git a/opengl/libs/EGL/MultifileBlobCache_test.cpp b/opengl/libs/EGL/MultifileBlobCache_test.cpp index fb765a73bc..85fb29ec40 100644 --- a/opengl/libs/EGL/MultifileBlobCache_test.cpp +++ b/opengl/libs/EGL/MultifileBlobCache_test.cpp @@ -21,6 +21,7 @@ #include <fcntl.h> #include <gtest/gtest.h> #include <stdio.h> +#include <utils/JenkinsHash.h> #include <fstream> #include <memory> @@ -855,4 +856,60 @@ TEST_F(MultifileBlobCacheTest, EvictAfterLostCache) { ASSERT_LE(getCacheEntries().size(), kMaxTotalEntries); } +// Remove from cache when size is zero +TEST_F(MultifileBlobCacheTest, ZeroSizeRemovesEntry) { + if (!flags::multifile_blobcache_advanced_usage()) { + GTEST_SKIP() << "Skipping test that requires multifile_blobcache_advanced_usage flag"; + } + + // Put some entries in + int entry = 0; + int result = 0; + + uint32_t kEntryCount = 20; + + // Add some entries + for (entry = 0; entry < kEntryCount; entry++) { + mMBC->set(&entry, sizeof(entry), &entry, sizeof(entry)); + ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result))); + ASSERT_EQ(entry, result); + } + + // Send some of them again with size zero + std::vector<int> removedEntries = {5, 10, 18}; + for (int i = 0; i < removedEntries.size(); i++) { + entry = removedEntries[i]; + mMBC->set(&entry, sizeof(entry), nullptr, 0); + } + + // Ensure they do not get a hit + for (int i = 0; i < removedEntries.size(); i++) { + entry = removedEntries[i]; + ASSERT_EQ(size_t(0), mMBC->get(&entry, sizeof(entry), &result, sizeof(result))); + } + + // And have been removed from disk + std::vector<std::string> diskEntries = getCacheEntries(); + ASSERT_EQ(diskEntries.size(), kEntryCount - removedEntries.size()); + for (int i = 0; i < removedEntries.size(); i++) { + entry = removedEntries[i]; + // Generate a hash for our removed entries and ensure they are not contained + // Note our entry and key and the same here, so we're hashing the key just like + // the multifile blobcache does. + uint32_t entryHash = + android::JenkinsHashMixBytes(0, reinterpret_cast<uint8_t*>(&entry), sizeof(entry)); + ASSERT_EQ(std::find(diskEntries.begin(), diskEntries.end(), std::to_string(entryHash)), + diskEntries.end()); + } + + // Ensure the others are still present + for (entry = 0; entry < kEntryCount; entry++) { + if (std::find(removedEntries.begin(), removedEntries.end(), entry) == + removedEntries.end()) { + ASSERT_EQ(sizeof(entry), mMBC->get(&entry, sizeof(entry), &result, sizeof(result))); + ASSERT_EQ(result, entry); + } + } +} + } // namespace android |