671 lines
20 KiB
C
671 lines
20 KiB
C
#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++;
|
|
}
|