Files
Strata/tests/platform/io_priority_test.cpp
Niko1221 b89bf5947d Windows: an engine started from a low-priority program no longer reads its model at Low disk priority; its disk priority goes back to Normal and one plain line says so (#4733)
A Windows process starts with the I/O priority of the program that started it. Run from a Task Scheduler task, a service, or a terminal that an IDE or coding agent keeps at low priority, the engine inherited Low I/O priority: the reporter measured PLE direct reads about 15x slower, cold prompt reads 3-5x slower and decode 14% slower on the same drive, and the engine blamed the drive. Both engines (strata and strata-dsv41) now read ProcessIoPriority at start and set it to Normal when it is lower (no privilege needed to go from Low to Normal). STRATA_KEEP_IO_PRIORITY=1 leaves it as inherited. The CPU priority class is not touched. New io_priority_test (Windows): started at Low it ends at Normal, started at Normal it is untouched, KEEP leaves Low alone. Tested here: that test passes on Windows; the HIP engine builds. Not tested: the reporter's slowdown itself (needs their drive and a low-priority launcher with an engine run).
2026-10-31 13:01:12 +01:00

44 lines
2.0 KiB
C++

// io_priority_test (#4733): on Windows a process that starts at Low I/O priority is put back to Normal; elsewhere the call does nothing.
#include "strata/platform/io_priority.hpp"
#include <cstdio>
#include <cstdlib>
#if defined(_WIN32)
#include <windows.h>
static unsigned long io_prio() {
using Query = LONG(NTAPI*)(HANDLE, ULONG, PVOID, ULONG, PULONG);
auto q = reinterpret_cast<Query>(reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryInformationProcess")));
ULONG v = 99, r = 0;
return q != nullptr && q(GetCurrentProcess(), 33, &v, sizeof v, &r) == 0 ? v : 99;
}
static bool set_io_prio(ULONG v) {
using Set = LONG(NTAPI*)(HANDLE, ULONG, PVOID, ULONG);
auto s = reinterpret_cast<Set>(reinterpret_cast<void*>(GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtSetInformationProcess")));
return s != nullptr && s(GetCurrentProcess(), 33, &v, sizeof v) == 0;
}
#endif
int main() {
#if defined(_WIN32)
int bad = 0;
// 1. started at Low: back to Normal, and the call reports what it found
if (!set_io_prio(1)) { std::printf("io_priority_test: SKIP (cannot lower the I/O priority here)\n"); return 77; }
int was = strata::platform::restore_normal_io_priority(stderr);
if (was != 1 || io_prio() != 2) { std::printf("FAIL lowered: was=%d now=%lu\n", was, io_prio()); ++bad; }
// 2. already Normal: untouched, reported as 2
was = strata::platform::restore_normal_io_priority(nullptr);
if (was != 2 || io_prio() != 2) { std::printf("FAIL normal: was=%d now=%lu\n", was, io_prio()); ++bad; }
// 3. STRATA_KEEP_IO_PRIORITY=1 leaves a low value alone
_putenv("STRATA_KEEP_IO_PRIORITY=1");
set_io_prio(1);
was = strata::platform::restore_normal_io_priority(nullptr);
if (was != -1 || io_prio() != 1) { std::printf("FAIL keep: was=%d now=%lu\n", was, io_prio()); ++bad; }
std::printf(bad == 0 ? "io_priority_test: OK\n" : "io_priority_test: %d FAILED\n", bad);
return bad == 0 ? 0 : 1;
#else
std::printf("io_priority_test: SKIP (Windows only)\n");
return 77;
#endif
}