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": [
"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": {
+53 -34
View File
@@ -276,6 +276,11 @@ namespace DiskCache {
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)) {
CacheFOZ.Unlock();
IndexFOZ.Unlock();
@@ -619,6 +624,12 @@ namespace DiskCache {
}
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?
if (Available < EntryUnderReview->GuestSize) {
continue;
@@ -649,7 +660,7 @@ namespace DiskCache {
break;
} else if (Validation) {
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* LiveGuest = reinterpret_cast<const uint8_t*>(GuestRIP);
uint64_t DiffCount = 0;
@@ -857,53 +868,55 @@ namespace DiskCache {
uint64_t LookupKey;
std::span<uint8_t> Blob;
fextl::vector<uint8_t> IndexBlob;
bool StoreDisk;
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)
, DB(DB)
, UniqueKey(UniqueKey)
, LookupKey(LookupKey)
, Blob(Blob)
, IndexBlob(std::move(IndexBlob)) {}
, IndexBlob(std::move(IndexBlob))
, StoreDisk(StoreDisk) {}
void Run() override {
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;
// todo possible other lru condition here like entry size?
if (Blob.size() > Self->MemoryLRUMaxSize) {
KeepEntryInMemory = false;
} else {
Self->MemoryLRUCurrentSize += Blob.size();
}
bool KeepEntryInMemory = true;
// todo possible other lru condition here like entry size?
if (Blob.size() > Self->MemoryLRUMaxSize) {
KeepEntryInMemory = false;
} else {
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;
if (KeepEntryInMemory) {
std::lock_guard Guard(Self->MemoryLRULock);
Self->MemoryLRU.push_front({LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint, (uint32_t)Blob.size()});
NewLRUEntry = Self->MemoryLRU.begin();
}
{
std::lock_guard Guard(Self->IndexLock);
auto IndexEntry = Self->LookupLocked(LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint);
LOGMAN_THROW_A_FMT(IndexEntry != nullptr, "Stored Index entry not found?");
if (IndexEntry) {
fextl::list<MemoryLRUKey>::iterator NewLRUEntry;
if (KeepEntryInMemory) {
std::lock_guard Guard(Self->MemoryLRULock);
Self->MemoryLRU.push_front({LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint, (uint32_t)Blob.size()});
NewLRUEntry = Self->MemoryLRU.begin();
}
{
std::lock_guard Guard(Self->IndexLock);
auto IndexEntry = Self->LookupLocked(LookupKey, IndexAfterHeader->GuestHash, IndexAfterHeader->GuestFootprint);
LOGMAN_THROW_A_FMT(IndexEntry != nullptr, "Stored Index entry not found?");
if (IndexEntry) {
if (StoreDisk && DiskSuccess) {
IndexEntry->DB = DB;
IndexEntry->Offset = IndexHeader.cache_db_file_offset;
if (!KeepEntryInMemory) {
IndexEntry->MemoryBlob.reset();
} else {
IndexEntry->LRUEntry = NewLRUEntry;
}
}
if (!KeepEntryInMemory) {
IndexEntry->MemoryBlob.reset();
} else {
IndexEntry->LRUEntry = NewLRUEntry;
}
}
}
if (KeepEntryInMemory && Self->MemoryLRUCurrentSize > Self->MemoryLRUMaxSize + Self->MemoryLRUEvictThreshold) {
Self->Writer->QueueWork(fextl::make_unique<PruneMemoryLRUWorkItem>(Self));
}
if (KeepEntryInMemory && Self->MemoryLRUCurrentSize > Self->MemoryLRUMaxSize + Self->MemoryLRUEvictThreshold) {
Self->Writer->QueueWork(fextl::make_unique<PruneMemoryLRUWorkItem>(Self));
}
}
};
@@ -1173,9 +1186,15 @@ namespace DiskCache {
memcpy(IndexBlob.data(), &IndexBlobHeader, sizeof(IndexExtraBlobHeader));
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
Writer->QueueWork(
fextl::make_unique<CacheStoreWorkItem>(this, RWCacheDB.get(), Key, LookupKey, std::span(BlobData, TotalSize), std::move(IndexBlob)));
Writer->QueueWork(fextl::make_unique<CacheStoreWorkItem>(this, RWCacheDB.get(), Key, LookupKey, std::span(BlobData, TotalSize),
std::move(IndexBlob), StoreDisk));
return true;
}
+7 -2
View File
@@ -168,18 +168,23 @@ namespace DiskCache {
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,
MesaFOZ::mesa_index_db_file_entry& IndexEntry, std::span<const uint8_t> IndexBlob);
bool Full() const {
return MaxSizeReached;
}
private:
// stores run on the Writer, so returning quick isn't as important
static constexpr uint32_t STORE_LOCK_TIMEOUT_MS = 1000;
static constexpr uint64_t BIG_MAPPING_SIZE = 1ULL << 33;
static constexpr uint32_t LOOKUP_KEY_MAX_BUCKET_DEPTH = 20;
FOZFile CacheFOZ;
uint8_t* CacheFileMapping = nullptr;
std::atomic<uint64_t> CacheFileSize;
FOZFile IndexFOZ;
bool ReadOnly = false;
bool MaxSizeReached = false;
FEX_CONFIG_OPT(MaxFileSize, DISKCACHEMAXFILESIZE);
};
class DiskCache {
@@ -246,7 +251,7 @@ namespace DiskCache {
// Be aware of the impact of changing this frequently!
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