#include <assert.h> #include <stdio.h> #include <string.h> #include <memory.h> #include <nt.h> #include <ntrtl.h> #include <nturtl.h> #include <windows.h> #define DbgPrint printf #define SEG_1_SIZE 1024 * 1024 #define SEG_X_SIZE 1024 * 1024 * 64 #define VM_MEMMAN_ITERATIONS 150 #define VM_MEMMAN_ITERATIONS2 2000 #define MemManSubtest5Count 200 int TotalBenchMarks = 0; #define MAX_BENCHMARKS 32 char *BenchMarkNames[ MAX_BENCHMARKS ]; ULONG BenchMarkRates[ MAX_BENCHMARKS ]; ULONG BenchMarkFracs[ MAX_BENCHMARKS ]; typedef struct _PERFINFO { LARGE_INTEGER StartTime; LARGE_INTEGER StopTime; PCHAR Title; ULONG Iterations; } PERFINFO, *PPERFINFO; int StartBenchMark( PCHAR Title, ULONG Iterations, PPERFINFO PerfInfo ); VOID FinishBenchMark( PPERFINFO PerfInfo ); __cdecl main() { PCHAR p1, p2, p3, p4; // pointers into new segment PCHAR pa[MemManSubtest5Count]; // array for section pointers PULONG u1; ULONG actual; // actual xfer count for read ULONG ssize; // section allocation size var ULONG ii, ix; // loop index variables PERFINFO PerfInfo; ULONG Seg1Size; ULONG SegxSize; ULONG CommitSize; NTSTATUS status; HANDLE CurrentProcessHandle, Section1; LARGE_INTEGER SectionSize; ULONG Size; ULONG ViewSize; DbgPrint("NT Memory Management test\n"); CurrentProcessHandle = NtCurrentProcess(); Size = 1024L * 1024L; p1 = NULL; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed allocvm - status %X\n", status); } for (p2=p1; p2 < (p1 + Size); p2 += 4) { u1 = (PULONG)p2; *u1 = (ULONG)p2; } // for SectionSize.LowPart = 1024*1024; SectionSize.HighPart = 0; status = NtCreateSection (&Section1, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(status)) { DbgPrint("service failed create sect - status %X\n", status); } p3 = NULL; ViewSize = 0; status = NtMapViewOfSection (Section1, CurrentProcessHandle, (PVOID *)&p3, 0L, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("service failed mapview - status %X\n", status); } RtlMoveMemory ((PVOID)p3, (PVOID)p1, Size); StartBenchMark( "NT MemMan00 -- 1 Meg Copy", 150, &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // for (ii=0; ii<150; ii++) { RtlMoveMemory ((PVOID)p3, (PVOID)p1, Size); } FinishBenchMark( &PerfInfo ); status = NtClose (Section1); if (!NT_SUCCESS(status)) { DbgPrint("service failed close sect - status %X\n", status); } status = NtUnmapViewOfSection (CurrentProcessHandle, p3); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %X\n", status); } // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // StartBenchMark( "NT MemMan01 -- create 1mb section, copy 1mb, delete", 150, &PerfInfo ); for (ii=0; ii<150; ii++) { status = NtCreateSection (&Section1, SECTION_MAP_READ | SECTION_MAP_WRITE, NULL, &SectionSize, PAGE_READWRITE, SEC_COMMIT, NULL); if (!NT_SUCCESS(status)) { DbgPrint("service failed create sect - status %X\n", status); } p3 = NULL; ViewSize = 0; status = NtMapViewOfSection (Section1, CurrentProcessHandle, (PVOID *)&p3, 0L, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("service failed mapview - status %X\n", status); } RtlMoveMemory ((PVOID)p3, (PVOID)p1, Size); p4 = NULL; ViewSize = 0; status = NtMapViewOfSection (Section1, CurrentProcessHandle, (PVOID *)&p4, 0L, 0, NULL, &ViewSize, ViewUnmap, 0, PAGE_READWRITE ); if (!NT_SUCCESS(status)) { DbgPrint("service failed mapview - status %X\n", status); } status = NtClose (Section1); if (!NT_SUCCESS(status)) { DbgPrint("service failed close sect - status %X\n", status); } status = NtUnmapViewOfSection (CurrentProcessHandle, p3); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %X\n", status); } status = NtUnmapViewOfSection (CurrentProcessHandle, p4); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %X\n", status); } } FinishBenchMark( &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // StartBenchMark( "NT MemMan02 -- alloc 1mb vm, copy 1mb, delete", 150, &PerfInfo ); for (ii=0; ii<150; ii++) { Size = 1024*1024; p3 = NULL; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, 0, &Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed allocvm - status %X\n", status); } RtlMoveMemory ((PVOID)p3, (PVOID)p1, Size); if (!NT_SUCCESS(status)) { DbgPrint("service failed close sect - status %X\n", status); } status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p3, &Size, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed freevm - status %X\n", status); } } FinishBenchMark( &PerfInfo ); status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Size, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed freevm - status %X\n", status); } // // start regular benchmarks. // StartBenchMark( "NT MemMan1 -- 1 Meg Seg, Create, Commit & Touch", VM_MEMMAN_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // for (ii=0; ii<VM_MEMMAN_ITERATIONS; ii++) { p1 = NULL; Seg1Size = SEG_1_SIZE; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Seg1Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } for (p2=p1; p2 < (p1 + Seg1Size); p2 += 4096) { u1 = (PULONG)p2; *u1=99; // for (ix=0; ix<1023; ix++) { // u1++; // if (*u1 != 0) DbgPrint("%lx = %lx\n",u1,*u1); // } } // for status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Seg1Size, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } FinishBenchMark( &PerfInfo ); StartBenchMark( "NT MemMan1.5 -- 1 Meg Seg, Create, reserve Commit & Touch", VM_MEMMAN_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 1 -- // // Create a 1 MB segment with commitment of the pages, // then touch each page, which should cause a fault and // a demand zero page to be allocated. // // for (ii=0; ii<VM_MEMMAN_ITERATIONS; ii++) { p1 = NULL; Seg1Size = SEG_1_SIZE; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Seg1Size, MEM_RESERVE | MEM_COMMIT, PAGE_READONLY); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } status = NtProtectVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Seg1Size, PAGE_READWRITE, &CommitSize); if (!NT_SUCCESS(status)) { DbgPrint("service failed (ntprotect)- status %lx\n", status); return 0; } for (p2=p1; p2 < (p1 + Seg1Size); p2 += 4096) { u1 = (PULONG)p2; *u1=99; // for (ix=0; ix<1023; ix++) { // u1++; // if (*u1 != 0) DbgPrint("%lx = %lx\n",u1,*u1); // } } // for status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Seg1Size, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } FinishBenchMark( &PerfInfo ); StartBenchMark( "NT MemMan2 -- 1 Meg Seg, Create & Commit Only", VM_MEMMAN_ITERATIONS2, &PerfInfo ); // // Memory Management sub-test 2 -- // // Create a 1 MB segment with commitment of the pages, // but never use the segment. // for (ii=0; ii<VM_MEMMAN_ITERATIONS2; ii++) { p1 = NULL; Seg1Size = SEG_1_SIZE; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Seg1Size, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Seg1Size, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } FinishBenchMark( &PerfInfo ); StartBenchMark( "NT MemMan3 -- 1 Meg Seg Create Only", VM_MEMMAN_ITERATIONS2, &PerfInfo ); // // Memory Management sub-test 3 -- // // Create a 1 MB segment without commitment of the pages, // but never use or commit the segment. // for (ii=0; ii<VM_MEMMAN_ITERATIONS2; ii++) { p1 = NULL; Seg1Size = SEG_1_SIZE; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &Seg1Size, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &Seg1Size, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } FinishBenchMark( &PerfInfo ); // // Reduce the number of iterations on this subtest for now. // When NT can perform it faster, up the interations again // #define VM_MMST04_ITERATIONS 4 //temporarily reduce the iterations StartBenchMark( "NT MemMan4 -- 64 Meg Seg, Commit Sparse", VM_MMST04_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 4 -- // // Create a 64 MB segment without committing the pages, // then commit and touch at 128 KB intervals. // // for (ii=0; ii<VM_MMST04_ITERATIONS; ii++) { p1 = NULL; SegxSize = SEG_X_SIZE; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, 0, &SegxSize, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } CommitSize = 4; for (p2=p1; p2 < (p1 + SegxSize); p2 += 256 * 1024) { status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&p2, 0, &CommitSize, MEM_COMMIT, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } if (*p2 != 0) DbgPrint("%lx = %lx\n",p2,*p2); } // for status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&p1, &SegxSize, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } FinishBenchMark( &PerfInfo ); // StartBenchMark( "NT MemMan5 -- Sparse Section Create/Delete Benchmark", VM_MEMMAN_ITERATIONS, &PerfInfo ); // // Memory Management sub-test 5 -- // // Create a alternatively 232k and 112 k memory sections. // For every 2 created, delete 1. Do this for MemManSubtest5Count times. // // for (ii=0; ii<VM_MEMMAN_ITERATIONS; ii++) { for (ix=0; ix<MemManSubtest5Count; ix++) { // // determine if even or odd allocation, if even and not 0, delete a section // ssize = (112 * 1024); //assume ODD allocation if ((ix & 1) == 0) { //if it is an even one ssize = (232 * 1024); //allocate 232 K on even passes if (ix){ //except on pass 0 SegxSize = 0; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&pa[ix/2], &SegxSize, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } pa[ix / 2] = 0; //remember this one is gone } } // end if even allocation pa[ix] = NULL; status = NtAllocateVirtualMemory (CurrentProcessHandle, (PVOID *)&pa[ix], 0, &ssize, MEM_RESERVE, PAGE_READWRITE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } // for ix // // Now free up the memory used in this test // for (ix=0; ix<MemManSubtest5Count; ix++) { if (pa[ix] != 0) { SegxSize = 0; status = NtFreeVirtualMemory (CurrentProcessHandle, (PVOID *)&pa[ix], &SegxSize, MEM_RELEASE); if (!NT_SUCCESS(status)) { DbgPrint("service failed - status %lx\n", status); } } // if } // for } // for ii FinishBenchMark( &PerfInfo ); DbgPrint("that's all\n"); return (TRUE); } int StartBenchMark( PCHAR Title, ULONG Iterations, PPERFINFO PerfInfo ) { DbgPrint( "*** Start %s (%d iterations)\n", PerfInfo->Title = Title, PerfInfo->Iterations = Iterations ); NtQuerySystemTime( (PLARGE_INTEGER)&PerfInfo->StartTime ); return( TRUE ); } VOID FinishBenchMark( PPERFINFO PerfInfo ) { ULONG TotalMilliSeconds; ULONG IterationsPerSecond; ULONG IterationFractions; LARGE_INTEGER Delta; NtQuerySystemTime( (PLARGE_INTEGER)&PerfInfo->StopTime ); Delta.QuadPart = PerfInfo->StopTime.QuadPart - PerfInfo->StartTime.QuadPart; TotalMilliSeconds = Delta.LowPart / 10000; IterationsPerSecond = (1000 * PerfInfo->Iterations) / TotalMilliSeconds; IterationFractions = (1000 * PerfInfo->Iterations) % TotalMilliSeconds; IterationFractions = (1000 * IterationFractions) / TotalMilliSeconds; if (1) { DbgPrint( " iterations - %9d\n", PerfInfo->Iterations ); DbgPrint( " milliseconds - %9d\n", TotalMilliSeconds ); DbgPrint( " iterations/sec - %5d.%3d\n\n", IterationsPerSecond, IterationFractions ); } BenchMarkNames[ TotalBenchMarks ] = PerfInfo->Title; BenchMarkRates[ TotalBenchMarks ] = IterationsPerSecond; BenchMarkFracs[ TotalBenchMarks ] = IterationFractions; TotalBenchMarks++; }