DiskCache: configurable max file size

This commit is contained in:
Pierre-Loup A. Griffais committed 2026-09-22 00:05:10 -07:00
1 parent 64a6da9aee
commit 83d8317dae
3 files changed
+68 -36

No files matched your search

@@ -221,6 +221,14 @@
"Desc": [ "Desc": [
"Optional list of extra read-only disk cache DBs to consider" "Optional list of extra read-only disk cache DBs to consider"
] ]
},
"DiskCacheMaxFileSize": {
"Type": "uint64",
"Default": "1073741824",
"AffectsCodeGen": "false",
"Desc": [
"Size limit on the main cache file - index not included. Default 1G"
]
} }
}, },
"Emulation": { "Emulation": {
+53 -34
View File
@@ -276,6 +276,11 @@ namespace DiskCache {
return false; return false;
} }
if (MaxSizeReached || CacheFileSize + Blob.size() >= MaxFileSize) {
MaxSizeReached = true;
return false;
}
if (!CacheFOZ.Lock(STORE_LOCK_TIMEOUT_MS) || !IndexFOZ.Lock(STORE_LOCK_TIMEOUT_MS)) { if (!CacheFOZ.Lock(STORE_LOCK_TIMEOUT_MS) || !IndexFOZ.Lock(STORE_LOCK_TIMEOUT_MS)) {
CacheFOZ.Unlock(); CacheFOZ.Unlock();
IndexFOZ.Unlock(); IndexFOZ.Unlock();
@@ -619,6 +624,12 @@ namespace DiskCache {
} }
Advance = true; Advance = true;
// entry not backed by anything right now - todo prune..
if (!EntryUnderReview->DB && !BlobRef) {
continue;
}
// do we have enough room in our live code to even hash GuestSize worth? // do we have enough room in our live code to even hash GuestSize worth?
if (Available < EntryUnderReview->GuestSize) { if (Available < EntryUnderReview->GuestSize) {
continue; continue;
@@ -649,7 +660,7 @@ namespace DiskCache {
break; break;
} else if (Validation) { } else if (Validation) {
fextl::vector<uint8_t> GuestCode(Entry.GuestSize); fextl::vector<uint8_t> GuestCode(Entry.GuestSize);
if (Entry.Size >= Entry.GuestSize && Entry.DB->ReadCacheBlob(Entry.Offset + Entry.Size - Entry.GuestSize, GuestCode)) { if (Entry.Size >= Entry.GuestSize && Entry.DB && Entry.DB->ReadCacheBlob(Entry.Offset + Entry.Size - Entry.GuestSize, GuestCode)) {
const uint8_t* CachedGuest = GuestCode.data(); const uint8_t* CachedGuest = GuestCode.data();
const uint8_t* LiveGuest = reinterpret_cast<const uint8_t*>(GuestRIP); const uint8_t* LiveGuest = reinterpret_cast<const uint8_t*>(GuestRIP);
uint64_t DiffCount = 0; uint64_t DiffCount = 0;
@@ -857,53 +868,55 @@ namespace DiskCache {
uint64_t LookupKey; uint64_t LookupKey;
std::span<uint8_t> Blob; std::span<uint8_t> Blob;
fextl::vector<uint8_t> IndexBlob; fextl::vector<uint8_t> IndexBlob;
bool StoreDisk;
CacheStoreWorkItem(DiskCache* Self, IndexedDB* DB, const MesaFOZ::foz_payload_key& UniqueKey, uint64_t LookupKey, CacheStoreWorkItem(DiskCache* Self, IndexedDB* DB, const MesaFOZ::foz_payload_key& UniqueKey, uint64_t LookupKey,
std::span<uint8_t> Blob, fextl::vector<uint8_t>&& IndexBlob) std::span<uint8_t> Blob, fextl::vector<uint8_t>&& IndexBlob, bool StoreDisk)
: Self(Self) : Self(Self)
, DB(DB) , DB(DB)
, UniqueKey(UniqueKey) , UniqueKey(UniqueKey)
, LookupKey(LookupKey) , LookupKey(LookupKey)
, Blob(Blob) , Blob(Blob)
, IndexBlob(std::move(IndexBlob)) {} , IndexBlob(std::move(IndexBlob))
, StoreDisk(StoreDisk) {}
void Run() override { void Run() override {
struct MesaFOZ::mesa_index_db_file_entry IndexHeader; struct MesaFOZ::mesa_index_db_file_entry IndexHeader;
bool Success = DB->StoreCacheBlob(UniqueKey, LookupKey, Blob, IndexHeader, IndexBlob); bool DiskSuccess = !StoreDisk || DB->StoreCacheBlob(UniqueKey, LookupKey, Blob, IndexHeader, IndexBlob);
if (Success) { bool KeepEntryInMemory = true;
bool KeepEntryInMemory = true; // todo possible other lru condition here like entry size?
// todo possible other lru condition here like entry size? if (Blob.size() > Self->MemoryLRUMaxSize) {
if (Blob.size() > Self->MemoryLRUMaxSize) { KeepEntryInMemory = false;
KeepEntryInMemory = false; } else {
} else { Self->MemoryLRUCurrentSize += Blob.size();
Self->MemoryLRUCurrentSize += Blob.size(); }
}
const IndexExtraBlobHeader* IndexAfterHeader = reinterpret_cast<const IndexExtraBlobHeader*>(IndexBlob.data()); const IndexExtraBlobHeader* IndexAfterHeader = reinterpret_cast<const IndexExtraBlobHeader*>(IndexBlob.data());
fextl::list<MemoryLRUKey>::iterator NewLRUEntry; fextl::list<MemoryLRUKey>::iterator NewLRUEntry;
if (KeepEntryInMemory) { if (KeepEntryInMemory) {
std::lock_guard Guard(Self->MemoryLRULock); std::lock_guard Guard(Self->MemoryLRULock);
Self->MemoryLRU.push_front({LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint, (uint32_t)Blob.size()}); Self->MemoryLRU.push_front({LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint, (uint32_t)Blob.size()});
NewLRUEntry = Self->MemoryLRU.begin(); NewLRUEntry = Self->MemoryLRU.begin();
} }
{ {
std::lock_guard Guard(Self->IndexLock); std::lock_guard Guard(Self->IndexLock);
auto IndexEntry = Self->LookupLocked(LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint); auto IndexEntry = Self->LookupLocked(LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint);
LOGMAN_THROW_A_FMT(IndexEntry != nullptr, "Stored Index entry not found?"); LOGMAN_THROW_A_FMT(IndexEntry != nullptr, "Stored Index entry not found?");
if (IndexEntry) { if (IndexEntry) {
if (StoreDisk && DiskSuccess) {
IndexEntry->DB = DB; IndexEntry->DB = DB;
IndexEntry->Offset = IndexHeader.cache_db_file_offset; IndexEntry->Offset = IndexHeader.cache_db_file_offset;
if (!KeepEntryInMemory) { }
IndexEntry->MemoryBlob.reset(); if (!KeepEntryInMemory) {
} else { IndexEntry->MemoryBlob.reset();
IndexEntry->LRUEntry = NewLRUEntry; } else {
} IndexEntry->LRUEntry = NewLRUEntry;
} }
} }
}
if (KeepEntryInMemory && Self->MemoryLRUCurrentSize > Self->MemoryLRUMaxSize + Self->MemoryLRUEvictThreshold) { if (KeepEntryInMemory && Self->MemoryLRUCurrentSize > Self->MemoryLRUMaxSize + Self->MemoryLRUEvictThreshold) {
Self->Writer->QueueWork(fextl::make_unique<PruneMemoryLRUWorkItem>(Self)); Self->Writer->QueueWork(fextl::make_unique<PruneMemoryLRUWorkItem>(Self));
}
} }
} }
}; };
@@ -1173,9 +1186,15 @@ namespace DiskCache {
memcpy(IndexBlob.data(), &IndexBlobHeader, sizeof(IndexExtraBlobHeader)); memcpy(IndexBlob.data(), &IndexBlobHeader, sizeof(IndexExtraBlobHeader));
memcpy(IndexBlob.data() + sizeof(IndexExtraBlobHeader), ExactGuestCodeExtents.data(), ExactGuestCodeExtents.size() * sizeof(uint32_t)); memcpy(IndexBlob.data() + sizeof(IndexExtraBlobHeader), ExactGuestCodeExtents.data(), ExactGuestCodeExtents.size() * sizeof(uint32_t));
bool StoreDisk = true;
if (RWCacheDB->Full()) {
StoreDisk = false;
}
// hand the rest off to the writer thread // hand the rest off to the writer thread
Writer->QueueWork( Writer->QueueWork(fextl::make_unique<CacheStoreWorkItem>(this, RWCacheDB.get(), Key, LookupKey, std::span(BlobData, TotalSize),
fextl::make_unique<CacheStoreWorkItem>(this, RWCacheDB.get(), Key, LookupKey, std::span(BlobData, TotalSize), std::move(IndexBlob))); std::move(IndexBlob), StoreDisk));
return true; return true;
} }
+7 -2
View File
@@ -168,18 +168,23 @@ namespace DiskCache {
bool ReadCacheBlob(uint64_t Offset, std::span<uint8_t> OutBlob); bool ReadCacheBlob(uint64_t Offset, std::span<uint8_t> OutBlob);
bool StoreCacheBlob(const MesaFOZ::foz_payload_key& UniqueKey, uint64_t LookupKey, std::span<const uint8_t> Blob, bool StoreCacheBlob(const MesaFOZ::foz_payload_key& UniqueKey, uint64_t LookupKey, std::span<const uint8_t> Blob,
MesaFOZ::mesa_index_db_file_entry& IndexEntry, std::span<const uint8_t> IndexBlob); MesaFOZ::mesa_index_db_file_entry& IndexEntry, std::span<const uint8_t> IndexBlob);
bool Full() const {
return MaxSizeReached;
}
private: private:
// stores run on the Writer, so returning quick isn't as important // stores run on the Writer, so returning quick isn't as important
static constexpr uint32_t STORE_LOCK_TIMEOUT_MS = 1000; static constexpr uint32_t STORE_LOCK_TIMEOUT_MS = 1000;
static constexpr uint64_t BIG_MAPPING_SIZE = 1ULL << 33; static constexpr uint64_t BIG_MAPPING_SIZE = 1ULL << 33;
static constexpr uint32_t LOOKUP_KEY_MAX_BUCKET_DEPTH = 20;
FOZFile CacheFOZ; FOZFile CacheFOZ;
uint8_t* CacheFileMapping = nullptr; uint8_t* CacheFileMapping = nullptr;
std::atomic<uint64_t> CacheFileSize; std::atomic<uint64_t> CacheFileSize;
FOZFile IndexFOZ; FOZFile IndexFOZ;
bool ReadOnly = false; bool ReadOnly = false;
bool MaxSizeReached = false;
FEX_CONFIG_OPT(MaxFileSize, DISKCACHEMAXFILESIZE);
}; };
class DiskCache { class DiskCache {
@@ -246,7 +251,7 @@ namespace DiskCache {
// Be aware of the impact of changing this frequently! // Be aware of the impact of changing this frequently!
static constexpr uint16_t FormatVersion = 26; static constexpr uint16_t FormatVersion = 26;
static constexpr uint32_t LOOKUP_KEY_MAX_BUCKET_DEPTH = 20; static constexpr uint32_t LOOKUP_KEY_MAX_BUCKET_DEPTH = 500;
} // namespace DiskCache } // namespace DiskCache