Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e893d3d9 authored by Cody Northrop's avatar Cody Northrop Committed by Android (Google) Code Review
Browse files

Merge "Reland "EGL BlobCache: Support multifile cache and flexible size limit""

parents 015ae27a 2c9085b0
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -160,6 +160,7 @@ cc_library_shared {
    srcs: [
        "EGL/egl_tls.cpp",
        "EGL/egl_cache.cpp",
        "EGL/egl_cache_multifile.cpp",
        "EGL/egl_display.cpp",
        "EGL/egl_object.cpp",
        "EGL/egl_layers.cpp",
+6 −0
Original line number Diff line number Diff line
@@ -185,4 +185,10 @@ void FileBlobCache::writeToFile() {
    }
}

size_t FileBlobCache::getSize() {
    if (mFilename.length() > 0) {
        return getFlattenedSize() + cacheFileHeaderSize;
    }
    return 0;
}
}
+3 −0
Original line number Diff line number Diff line
@@ -33,6 +33,9 @@ public:
    // disk.
    void writeToFile();

    // Return the total size of the cache
    size_t getSize();

private:
    // mFilename is the name of the file for storing cache contents.
    std::string mFilename;
+94 −21
Original line number Diff line number Diff line
@@ -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 @@ static EGLsizeiANDROID getBlob(const void* key, EGLsizeiANDROID keySize, void* v
//
// 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 @@ void egl_cache_t::initialize(egl_display_t* display) {
        }
    }

    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 @@ void egl_cache_t::terminate() {
        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,6 +149,22 @@ void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, const void*
    }

    if (mInitialized) {
        if (mMultifileMode) {
            setBlobMultifile(key, keySize, value, valueSize, mFilename);

            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);

@@ -139,20 +182,25 @@ void egl_cache_t::setBlob(const void* key, EGLsizeiANDROID keySize, const void*
            }
        }
    }
}

EGLsizeiANDROID egl_cache_t::getBlob(const void* key, EGLsizeiANDROID keySize, void* value,
                                     EGLsizeiANDROID valueSize) {
    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) {
        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 @@ void egl_cache_t::setCacheFilename(const char* filename) {
    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();
}
+16 −0
Original line number Diff line number Diff line
@@ -64,6 +64,12 @@ public:
    // cache contents from one program invocation to another.
    void setCacheFilename(const char* filename);

    // Allow the fixed cache limit to be overridden
    void setCacheLimit(int64_t cacheByteLimit);

    // Return the byte total for cache file(s)
    size_t getCacheSize();

private:
    // Creation and (the lack of) destruction is handled internally.
    egl_cache_t();
@@ -112,6 +118,16 @@ private:

    // sCache is the singleton egl_cache_t object.
    static egl_cache_t sCache;

    // Whether to use multiple files to store cache entries
    bool mMultifileMode;

    // Cache limit
    int64_t mCacheByteLimit;

    // Whether we've kicked off a side thread that will check the multifile
    // cache size and remove entries if needed.
    bool mMultifileCleanupPending;
};

}; // namespace android
Loading