Created
September 7, 2018 17:22
-
-
Save Kalinovcic/ca2c346ec7622216da45b252bad1581f to your computer and use it in GitHub Desktop.
Some code using undocumented NT profiling functions to count LLC misses. I don't know how accurate it is, haven't used it for anything yet.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
typedef enum _KPROFILE_SOURCE | |
{ | |
ProfileTime = 0x00, | |
ProfileTotalIssues = 0x02, | |
ProfileBranchInstructions = 0x06, | |
ProfileCacheMisses = 0x0A, | |
ProfileBranchMispredictions = 0x0B, | |
ProfileTotalCycles = 0x13, | |
ProfileUnhaltedCoreCycles = 0x19, | |
ProfileInstructionRetired = 0x1A, | |
ProfileUnhaltedReferenceCycles = 0x1B, | |
ProfileLLCReference = 0x1C, | |
ProfileLLCMisses = 0x1D, | |
ProfileBranchInstructionRetired = 0x1E, | |
ProfileBranchMispredictsRetired = 0x1F, | |
} KPROFILE_SOURCE, *PKPROFILE_SOURCE; | |
typedef NTSYSAPI NTSTATUS NTAPI F_NtCreateProfile( | |
OUT PHANDLE ProfileHandle, | |
IN HANDLE Process OPTIONAL, | |
IN PVOID ImageBase, | |
IN ULONG ImageSize, | |
IN ULONG BucketSize, | |
IN PVOID Buffer, | |
IN ULONG BufferSize, | |
IN KPROFILE_SOURCE ProfileSource, | |
IN KAFFINITY Affinity | |
); | |
typedef NTSYSAPI NTSTATUS NTAPI F_NtStartProfile( | |
IN HANDLE ProfileHandle | |
); | |
typedef NTSYSAPI NTSTATUS NTAPI F_NtStopProfile( | |
IN HANDLE ProfileHandle | |
); | |
HMODULE GetCurrentModule() | |
{ | |
HMODULE module = NULL; | |
GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCWSTR) GetCurrentModule, &module); | |
return module; | |
} | |
void test() | |
{ | |
HMODULE nt = LoadLibraryA("ntdll.dll"); | |
F_NtCreateProfile* NtCreateProfile = (F_NtCreateProfile*) GetProcAddress(nt, "NtCreateProfile"); | |
F_NtStartProfile* NtStartProfile = (F_NtStartProfile*) GetProcAddress(nt, "NtStartProfile"); | |
F_NtStopProfile* NtStopProfile = (F_NtStopProfile*) GetProcAddress(nt, "NtStopProfile"); | |
HANDLE process = GetCurrentProcess(); | |
HMODULE module = GetCurrentModule(); | |
printf("%p %p\n", process, module); | |
MODULEINFO module_info; | |
BOOL module_info_success = GetModuleInformation(process, module, &module_info, sizeof(module_info)); | |
if (!module_info_success) | |
{ | |
printf("GetModuleInformation() failed!\n"); | |
return; | |
} | |
void* image_base = module_info.lpBaseOfDll; | |
umm image_size = module_info.SizeOfImage; | |
printf("%p\n", image_base); | |
printf("%d\n", (int) image_size); | |
HANDLE profile; | |
ULONG buffer[1] = {}; | |
NTSTATUS create_status = NtCreateProfile(&profile, process, image_base, image_size, 30, buffer, 4, ProfileLLCMisses, -1); | |
printf("NtCreateProfile: %x\n", create_status); | |
NtStartProfile(profile); | |
{ | |
int* matrix = (int*) malloc(sizeof(int) * 16 * 1024 * 16 * 1024); | |
for (int i = 0; i < 10000; i++) | |
for (int j = 0; j < 10000; j++) | |
matrix[i * 16 * 1024 + j] *= i * j; | |
free(matrix); | |
} | |
NtStopProfile(profile); | |
printf("Cache misses 1: %d\n", buffer[0]); | |
buffer[0] = 0; | |
NtStartProfile(profile); | |
{ | |
int* matrix = (int*) malloc(sizeof(int) * 16 * 1024 * 16 * 1024); | |
for (int i = 0; i < 10000; i++) | |
for (int j = 0; j < 10000; j++) | |
matrix[j * 16 * 1024 + i] *= i * j; | |
free(matrix); | |
} | |
NtStopProfile(profile); | |
printf("Cache misses 2: %d\n", buffer[0]); | |
buffer[0] = 0; | |
exit(0); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment