Add support for probing page fault behaviour on Windows
This commit is contained in:
parent
9104a41e2d
commit
f18ecde7bc
@ -1,12 +1,61 @@
|
||||
#include "aliases.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#define PAGESIZE 4096
|
||||
|
||||
#if _WIN32
|
||||
|
||||
#include <intrin.h>
|
||||
#include <psapi.h>
|
||||
#include <windows.h>
|
||||
|
||||
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 <sys/mman.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#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;
|
||||
|
Loading…
Reference in New Issue
Block a user