From f18ecde7bc09de3e8eebb545d873c7e6d93a7a2d Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Sun, 24 Sep 2023 17:35:23 +0100 Subject: [PATCH] Add support for probing page fault behaviour on Windows --- haversine_02/src/memtester/main.c | 81 +++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 4 deletions(-) diff --git a/haversine_02/src/memtester/main.c b/haversine_02/src/memtester/main.c index 6065133..857c919 100644 --- a/haversine_02/src/memtester/main.c +++ b/haversine_02/src/memtester/main.c @@ -1,12 +1,61 @@ #include "aliases.h" +#include #include #include + +#define PAGESIZE 4096 + +#if _WIN32 + +#include +#include +#include + +typedef struct { + bool Initialized; + HANDLE ProcessHandle; +} os_metrics; + +static os_metrics GlobalMetrics; + +static u64 GetOSTimerFreq(void) { + LARGE_INTEGER Freq; + QueryPerformanceFrequency(&Freq); + return Freq.QuadPart; +} + +static u64 ReadOSTimer(void) { + LARGE_INTEGER Value; + QueryPerformanceCounter(&Value); + return Value.QuadPart; +} + +static u64 ReadOSPageFaultCount(void) { + PROCESS_MEMORY_COUNTERS_EX MemoryCounters = {}; + MemoryCounters.cb = sizeof(MemoryCounters); + GetProcessMemoryInfo(GlobalMetrics.ProcessHandle, + (PROCESS_MEMORY_COUNTERS *)&MemoryCounters, + sizeof(MemoryCounters)); + + u64 Result = MemoryCounters.PageFaultCount; + return Result; +} + +static void InitializeOSMetrics(void) { + if (!GlobalMetrics.Initialized) { + GlobalMetrics.Initialized = true; + GlobalMetrics.ProcessHandle = + OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, + GetCurrentProcessId()); + } +} + +#else // _WIN32 + #include #include #include -#define PAGESIZE 4096 - typedef struct rusage rusage_t; u64 page_fault_count() { @@ -17,6 +66,8 @@ u64 page_fault_count() { return usage.ru_minflt + usage.ru_majflt; } +#endif // _WIN32 + int main(int argc, char *argv[]) { if (argc < 2 || argc > 2) { printf("Usage: %s [NUMBER OF PAGES TO ALLOCATE]\n", argv[0]); @@ -24,6 +75,10 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } +#if _WIN32 + InitializeOSMetrics(); +#endif + u64 page_count = atol(argv[1]); u64 alloc_size = page_count * PAGESIZE; u64 touch_size = 0; @@ -33,8 +88,13 @@ int main(int argc, char *argv[]) { for (u64 touch_count = 0; touch_count <= page_count; ++touch_count) { touch_size = touch_count * PAGESIZE; +#if _WIN32 + u8 *data = (u8 *)VirtualAlloc(0, alloc_size, MEM_RESERVE | MEM_COMMIT, + PAGE_READWRITE); +#else u8 *data = (u8 *)mmap(NULL, alloc_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); +#endif if (!data) { printf("Failed to allocate memory\n"); @@ -42,20 +102,33 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } +#if _WIN32 + u64 fault_start = ReadOSPageFaultCount(); +#else u64 fault_start = page_fault_count(); +#endif for (u64 i = 0; i < touch_size; ++i) { data[i] = (u8)i; } +#if _WIN32 + u64 fault_end = ReadOSPageFaultCount(); +#else u64 fault_end = page_fault_count(); +#endif u64 faults = fault_end - fault_start; - printf("%lu,%lu,%lu,%ld\n", page_count, touch_count, faults, - ((i64)faults - touch_count)); + printf("%llu,%llu,%llu,%lld\n", (unsigned long long)page_count, + (unsigned long long)touch_count, (unsigned long long)faults, + ((long long)faults - touch_count)); +#if _WIN32 + VirtualFree(Data, 0, MEM_RELEASE); +#else munmap((void *)data, alloc_size); +#endif } return EXIT_SUCCESS;