From b8a2e9ef69a6abb44b0047575fcb3ed579533af1 Mon Sep 17 00:00:00 2001 From: Takoroka <137927095+Takoroka@users.noreply.github.com> Date: Wed, 28 Oct 2026 05:55:09 -0400 Subject: vfs: keep the open-file cache below the CRT limit The real VFS kept up to 8192 host files open, which is also the most the Windows C runtime allows (_setmaxstdio(8192)). A game read from a loose RomFS folder fills that within minutes (title 4: ~7300 handles after 160 s); from then on every other open failed with "too many files open" - its next scene pack, its save file, the shader cache - and the game waited forever on the load. Cap the cache 512 below _getmaxstdio() on Windows. --- src/core/file_sys/vfs/vfs_real.cpp | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) (limited to 'src/core/file_sys') diff --git a/src/core/file_sys/vfs/vfs_real.cpp b/src/core/file_sys/vfs/vfs_real.cpp index 14e0caad3c..fd36752fee 100644 --- a/src/core/file_sys/vfs/vfs_real.cpp +++ b/src/core/file_sys/vfs/vfs_real.cpp @@ -19,6 +19,10 @@ // For FileTimeStampRaw #include +#ifdef _WIN32 +#include // _getmaxstdio +#endif + #ifdef _MSC_VER #define stat _stat64 #endif @@ -33,7 +37,17 @@ namespace FS = Common::FS; namespace { -constexpr size_t MaxOpenFiles = 8192; +// Files the cache keeps open. On Windows it has to stay below the C runtime's open-file limit with +// room to spare: at the limit every other open fails (saves, shader caches, and the cache's own +// next file, which it only evicts for once it reaches its cap). +size_t MaxOpenFiles() { +#ifdef _WIN32 + static const size_t limit = static_cast((std::max)(_getmaxstdio() - 512, 64)); + return (std::min)(size_t{8192}, limit); +#else + return 8192; +#endif +} bool IsWithinRoot(std::string_view root, std::string_view full_path) { if (root.empty()) @@ -251,7 +265,7 @@ void RealVfsFilesystem::DropReference(std::unique_ptr&& reference } void RealVfsFilesystem::EvictSingleReferenceLocked() { - if (num_open_files < MaxOpenFiles || open_references.empty()) { + if (num_open_files < MaxOpenFiles() || open_references.empty()) { return; } -- cgit v1.2.3