Add support for probing page fault behaviour on Windows
This commit is contained in:
		@@ -1,12 +1,61 @@
 | 
				
			|||||||
#include "aliases.h"
 | 
					#include "aliases.h"
 | 
				
			||||||
 | 
					#include <stdbool.h>
 | 
				
			||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
#include <stdlib.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/mman.h>
 | 
				
			||||||
#include <sys/resource.h>
 | 
					#include <sys/resource.h>
 | 
				
			||||||
#include <sys/time.h>
 | 
					#include <sys/time.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define PAGESIZE 4096
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct rusage rusage_t;
 | 
					typedef struct rusage rusage_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
u64 page_fault_count() {
 | 
					u64 page_fault_count() {
 | 
				
			||||||
@@ -17,6 +66,8 @@ u64 page_fault_count() {
 | 
				
			|||||||
  return usage.ru_minflt + usage.ru_majflt;
 | 
					  return usage.ru_minflt + usage.ru_majflt;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif // _WIN32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int main(int argc, char *argv[]) {
 | 
					int main(int argc, char *argv[]) {
 | 
				
			||||||
  if (argc < 2 || argc > 2) {
 | 
					  if (argc < 2 || argc > 2) {
 | 
				
			||||||
    printf("Usage: %s [NUMBER OF PAGES TO ALLOCATE]\n", argv[0]);
 | 
					    printf("Usage: %s [NUMBER OF PAGES TO ALLOCATE]\n", argv[0]);
 | 
				
			||||||
@@ -24,6 +75,10 @@ int main(int argc, char *argv[]) {
 | 
				
			|||||||
    return EXIT_FAILURE;
 | 
					    return EXIT_FAILURE;
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if _WIN32
 | 
				
			||||||
 | 
					  InitializeOSMetrics();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  u64 page_count = atol(argv[1]);
 | 
					  u64 page_count = atol(argv[1]);
 | 
				
			||||||
  u64 alloc_size = page_count * PAGESIZE;
 | 
					  u64 alloc_size = page_count * PAGESIZE;
 | 
				
			||||||
  u64 touch_size = 0;
 | 
					  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) {
 | 
					  for (u64 touch_count = 0; touch_count <= page_count; ++touch_count) {
 | 
				
			||||||
    touch_size = touch_count * PAGESIZE;
 | 
					    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,
 | 
					    u8 *data = (u8 *)mmap(NULL, alloc_size, PROT_READ | PROT_WRITE,
 | 
				
			||||||
                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 | 
					                          MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (!data) {
 | 
					    if (!data) {
 | 
				
			||||||
      printf("Failed to allocate memory\n");
 | 
					      printf("Failed to allocate memory\n");
 | 
				
			||||||
@@ -42,20 +102,33 @@ int main(int argc, char *argv[]) {
 | 
				
			|||||||
      return EXIT_FAILURE;
 | 
					      return EXIT_FAILURE;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if _WIN32
 | 
				
			||||||
 | 
					    u64 fault_start = ReadOSPageFaultCount();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
    u64 fault_start = page_fault_count();
 | 
					    u64 fault_start = page_fault_count();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (u64 i = 0; i < touch_size; ++i) {
 | 
					    for (u64 i = 0; i < touch_size; ++i) {
 | 
				
			||||||
      data[i] = (u8)i;
 | 
					      data[i] = (u8)i;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if _WIN32
 | 
				
			||||||
 | 
					    u64 fault_end = ReadOSPageFaultCount();
 | 
				
			||||||
 | 
					#else
 | 
				
			||||||
    u64 fault_end = page_fault_count();
 | 
					    u64 fault_end = page_fault_count();
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    u64 faults = fault_end - fault_start;
 | 
					    u64 faults = fault_end - fault_start;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    printf("%lu,%lu,%lu,%ld\n", page_count, touch_count, faults,
 | 
					    printf("%llu,%llu,%llu,%lld\n", (unsigned long long)page_count,
 | 
				
			||||||
           ((i64)faults - touch_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);
 | 
					    munmap((void *)data, alloc_size);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return EXIT_SUCCESS;
 | 
					  return EXIT_SUCCESS;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user