change ImageMetadataDatabase caches to use a TTL

This commit is contained in:
Kae 2024-10-15 16:11:17 +11:00
parent 4b917e8c2f
commit be884c33b4
3 changed files with 53 additions and 28 deletions

View File

@ -10,17 +10,28 @@
namespace Star { namespace Star {
ImageMetadataDatabase::ImageMetadataDatabase() {
MutexLocker locker(m_mutex);
int timeSmear = 2000;
int64_t timeToLive = 60000;
m_sizeCache.setTimeSmear(timeSmear);
m_spacesCache.setTimeSmear(timeSmear);
m_regionCache.setTimeSmear(timeSmear);
m_sizeCache.setTimeToLive(timeToLive);
m_spacesCache.setTimeToLive(timeToLive);
m_regionCache.setTimeToLive(timeToLive);
}
Vec2U ImageMetadataDatabase::imageSize(AssetPath const& path) const { Vec2U ImageMetadataDatabase::imageSize(AssetPath const& path) const {
MutexLocker locker(m_mutex); MutexLocker locker(m_mutex);
auto i = m_sizeCache.find(path); if (auto cached = m_sizeCache.ptr(path))
if (i != m_sizeCache.end()) return *cached;
return i->second;
locker.unlock(); locker.unlock();
Vec2U size = calculateImageSize(path); Vec2U size = calculateImageSize(path);
locker.lock(); locker.lock();
m_sizeCache[path] = size; m_sizeCache.set(path, size);
return size; return size;
} }
@ -28,19 +39,16 @@ List<Vec2I> ImageMetadataDatabase::imageSpaces(AssetPath const& path, Vec2F posi
SpacesEntry key = make_tuple(path, Vec2I::round(position), fillLimit, flip); SpacesEntry key = make_tuple(path, Vec2I::round(position), fillLimit, flip);
MutexLocker locker(m_mutex); MutexLocker locker(m_mutex);
auto i = m_spacesCache.find(key); if (auto cached = m_spacesCache.ptr(key)) {
if (i != m_spacesCache.end()) { return *cached;
return i->second;
} }
auto filteredPath = filterProcessing(path); auto filteredPath = filterProcessing(path);
SpacesEntry filteredKey = make_tuple(filteredPath, Vec2I::round(position), fillLimit, flip); SpacesEntry filteredKey = make_tuple(filteredPath, Vec2I::round(position), fillLimit, flip);
auto j = m_spacesCache.find(filteredKey); if (auto cached = m_spacesCache.ptr(filteredKey)) {
if (j != m_spacesCache.end()) { m_spacesCache.set(key, *cached);
auto spaces = j->second; return *cached;
m_spacesCache[key] = spaces;
return spaces;
} }
locker.unlock(); locker.unlock();
@ -82,24 +90,23 @@ List<Vec2I> ImageMetadataDatabase::imageSpaces(AssetPath const& path, Vec2F posi
} }
locker.lock(); locker.lock();
m_spacesCache[key] = spaces; m_spacesCache.set(key, spaces);
m_spacesCache[filteredKey] = spaces; m_spacesCache.set(filteredKey, spaces);
return spaces; return spaces;
} }
RectU ImageMetadataDatabase::nonEmptyRegion(AssetPath const& path) const { RectU ImageMetadataDatabase::nonEmptyRegion(AssetPath const& path) const {
MutexLocker locker(m_mutex); MutexLocker locker(m_mutex);
auto i = m_regionCache.find(path);
if (i != m_regionCache.end()) { if (auto cached = m_regionCache.ptr(path)) {
return i->second; return *cached;
} }
auto filteredPath = filterProcessing(path); auto filteredPath = filterProcessing(path);
auto j = m_regionCache.find(filteredPath); if (auto cached = m_regionCache.ptr(filteredPath)) {
if (j != m_regionCache.end()) { m_regionCache.set(path, *cached);
m_regionCache[path] = j->second; return *cached;
return j->second;
} }
locker.unlock(); locker.unlock();
@ -111,12 +118,20 @@ RectU ImageMetadataDatabase::nonEmptyRegion(AssetPath const& path) const {
}); });
locker.lock(); locker.lock();
m_regionCache[path] = region; m_regionCache.set(path, region);
m_regionCache[filteredPath] = region; m_regionCache.set(filteredPath, region);
return region; return region;
} }
void ImageMetadataDatabase::cleanup() const {
MutexLocker locker(m_mutex);
m_sizeCache.cleanup();
m_spacesCache.cleanup();
m_regionCache.cleanup();
}
AssetPath ImageMetadataDatabase::filterProcessing(AssetPath const& path) { AssetPath ImageMetadataDatabase::filterProcessing(AssetPath const& path) {
AssetPath newPath = { path.basePath, path.subPath, {} }; AssetPath newPath = { path.basePath, path.subPath, {} };
@ -170,7 +185,7 @@ Vec2U ImageMetadataDatabase::calculateImageSize(AssetPath const& path) const {
// so we don't have to call Image::readPngMetadata on the same file more // so we don't have to call Image::readPngMetadata on the same file more
// than once. // than once.
MutexLocker locker(m_mutex); MutexLocker locker(m_mutex);
if (auto size = m_sizeCache.maybe(path.basePath)) { if (auto size = m_sizeCache.ptr(path.basePath)) {
imageSize = *size; imageSize = *size;
} else { } else {
locker.unlock(); locker.unlock();
@ -180,7 +195,7 @@ Vec2U ImageMetadataDatabase::calculateImageSize(AssetPath const& path) const {
else else
imageSize = fallback(); imageSize = fallback();
locker.lock(); locker.lock();
m_sizeCache[path.basePath] = imageSize; m_sizeCache.set(path.basePath, imageSize);
} }
} }

View File

@ -5,6 +5,7 @@
#include "StarString.hpp" #include "StarString.hpp"
#include "StarThread.hpp" #include "StarThread.hpp"
#include "StarAssetPath.hpp" #include "StarAssetPath.hpp"
#include "StarTtlCache.hpp"
namespace Star { namespace Star {
@ -15,9 +16,11 @@ STAR_CLASS(ImageMetadataDatabase);
// because they are expensive to compute and cheap to keep around. // because they are expensive to compute and cheap to keep around.
class ImageMetadataDatabase { class ImageMetadataDatabase {
public: public:
ImageMetadataDatabase();
Vec2U imageSize(AssetPath const& path) const; Vec2U imageSize(AssetPath const& path) const;
List<Vec2I> imageSpaces(AssetPath const& path, Vec2F position, float fillLimit, bool flip) const; List<Vec2I> imageSpaces(AssetPath const& path, Vec2F position, float fillLimit, bool flip) const;
RectU nonEmptyRegion(AssetPath const& path) const; RectU nonEmptyRegion(AssetPath const& path) const;
void cleanup() const;
private: private:
// Removes image processing directives that don't affect image spaces / // Removes image processing directives that don't affect image spaces /
@ -30,9 +33,9 @@ private:
typedef tuple<AssetPath, Vec2I, float, bool> SpacesEntry; typedef tuple<AssetPath, Vec2I, float, bool> SpacesEntry;
mutable Mutex m_mutex; mutable Mutex m_mutex;
mutable HashMap<AssetPath, Vec2U> m_sizeCache; mutable HashTtlCache<AssetPath, Vec2U> m_sizeCache;
mutable HashMap<SpacesEntry, List<Vec2I>> m_spacesCache; mutable HashTtlCache<SpacesEntry, List<Vec2I>> m_spacesCache;
mutable HashMap<AssetPath, RectU> m_regionCache; mutable HashTtlCache<AssetPath, RectU> m_regionCache;
}; };
} }

View File

@ -137,6 +137,13 @@ Root::Root(Settings settings) : RootBase() {
tenantDb->cleanup(); tenantDb->cleanup();
} }
} }
{
MutexLocker locker(m_imageMetadataDatabaseMutex);
if (ImageMetadataDatabasePtr imgMetaDb = m_imageMetadataDatabase) {
locker.unlock();
imgMetaDb->cleanup();
}
}
Random::addEntropy(); Random::addEntropy();