From 33b4060b6ad2c2c74b06678d0ece72fb0301dfe9 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Wed, 13 May 2026 07:47:44 -0500 Subject: [PATCH] Move statvfs cache to use shared mutex Its read heavy and micro benchmarks show no regression on the low end and 30%+ throughput improvements on the highend. --- src/fs_statvfs_cache.cpp | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/src/fs_statvfs_cache.cpp b/src/fs_statvfs_cache.cpp index 1d2fa708..891708da 100644 --- a/src/fs_statvfs_cache.cpp +++ b/src/fs_statvfs_cache.cpp @@ -21,8 +21,8 @@ #include "fs_statvfs.hpp" #include "statvfs_util.hpp" -#include "mutex.hpp" - +#include +#include #include #include @@ -38,9 +38,11 @@ struct Element typedef std::unordered_map statvfs_cache; -static u64 g_timeout = 0; -static statvfs_cache g_cache; -static Mutex g_cache_lock; +// Cache is read heavy. Use a shared mutex so concurrent reads can +// work in parallel and only inserts or refreshes take a unique lock. +static std::shared_mutex g_cache_mutex; +static u64 g_timeout = 0; +static statvfs_cache g_cache; static @@ -70,29 +72,35 @@ int fs::statvfs_cache(const std::string &path_, struct statvfs *st_) { - int rv; - Element *e; u64 now; if(g_timeout == 0) return fs::statvfs(path_,st_); - rv = 0; now = ::_get_time(); - mutex_lock(g_cache_lock); + { + std::shared_lock lk(g_cache_mutex); - e = &g_cache[path_]; + auto it = g_cache.find(path_); + if((it != g_cache.end()) && ((now - it->second.time) <= g_timeout)) + { + *st_ = it->second.st; + return 0; + } + } - if((now - e->time) > g_timeout) + int rv = 0; + std::unique_lock lk(g_cache_mutex); + + Element &e = g_cache[path_]; + if((now - e.time) > g_timeout) { - e->time = now; - rv = fs::statvfs(path_,&e->st); + e.time = now; + rv = fs::statvfs(path_,&e.st); } - *st_ = e->st; - - mutex_unlock(g_cache_lock); + *st_ = e.st; return rv; }