218 lines
5.4 KiB
C
218 lines
5.4 KiB
C
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <assert.h>
|
||
#include <stdlib.h>
|
||
#include <stdio.h>
|
||
#include <windows.h>
|
||
#include <string.h>
|
||
#include <memory.h>
|
||
#include <process.h>
|
||
|
||
#define WAIT_MULTIPLE_ITERATIONS 10000
|
||
HANDLE WaitHandles[64];
|
||
|
||
//
|
||
// Define local types.
|
||
//
|
||
|
||
typedef struct _PERFINFO {
|
||
LARGE_INTEGER StartTime;
|
||
LARGE_INTEGER StopTime;
|
||
ULONG ContextSwitches;
|
||
ULONG FirstLevelFills;
|
||
ULONG SecondLevelFills;
|
||
ULONG SystemCalls;
|
||
PCHAR Title;
|
||
ULONG Iterations;
|
||
} PERFINFO, *PPERFINFO;
|
||
|
||
VOID
|
||
FinishBenchMark (
|
||
IN PPERFINFO PerfInfo
|
||
)
|
||
|
||
{
|
||
|
||
ULONG ContextSwitches;
|
||
LARGE_INTEGER Duration;
|
||
ULONG FirstLevelFills;
|
||
ULONG Length;
|
||
ULONG Performance;
|
||
ULONG SecondLevelFills;
|
||
NTSTATUS Status;
|
||
ULONG SystemCalls;
|
||
SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
|
||
|
||
|
||
//
|
||
// Print results and announce end of test.
|
||
//
|
||
|
||
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StopTime);
|
||
Status = NtQuerySystemInformation(SystemPerformanceInformation,
|
||
(PVOID)&SystemInfo,
|
||
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
|
||
NULL);
|
||
|
||
if (NT_SUCCESS(Status) == FALSE) {
|
||
printf("Failed to query performance information, status = %lx\n", Status);
|
||
return;
|
||
}
|
||
|
||
Duration = RtlLargeIntegerSubtract(PerfInfo->StopTime, PerfInfo->StartTime);
|
||
Length = Duration.LowPart / 10000;
|
||
printf(" Test time in milliseconds %d\n", Length);
|
||
printf(" Number of iterations %d\n", PerfInfo->Iterations);
|
||
|
||
Performance = PerfInfo->Iterations * 1000 / Length;
|
||
printf(" Iterations per second %d\n", Performance);
|
||
|
||
ContextSwitches = SystemInfo.ContextSwitches - PerfInfo->ContextSwitches;
|
||
FirstLevelFills = SystemInfo.FirstLevelTbFills - PerfInfo->FirstLevelFills;
|
||
SecondLevelFills = SystemInfo.SecondLevelTbFills - PerfInfo->SecondLevelFills;
|
||
SystemCalls = SystemInfo.SystemCalls - PerfInfo->SystemCalls;
|
||
printf(" First Level TB Fills %d\n", FirstLevelFills);
|
||
printf(" Second Level TB Fills %d\n", SecondLevelFills);
|
||
printf(" Total Context Switches %d\n", ContextSwitches);
|
||
printf(" Number of System Calls %d\n", SystemCalls);
|
||
|
||
printf("*** End of Test ***\n\n");
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
StartBenchMark (
|
||
IN PCHAR Title,
|
||
IN ULONG Iterations,
|
||
IN PPERFINFO PerfInfo
|
||
)
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
|
||
|
||
//
|
||
// Announce start of test and the number of iterations.
|
||
//
|
||
|
||
printf("*** Start of test ***\n %s\n", Title);
|
||
PerfInfo->Title = Title;
|
||
PerfInfo->Iterations = Iterations;
|
||
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StartTime);
|
||
Status = NtQuerySystemInformation(SystemPerformanceInformation,
|
||
(PVOID)&SystemInfo,
|
||
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
|
||
NULL);
|
||
|
||
if (NT_SUCCESS(Status) == FALSE) {
|
||
printf("Failed to query performance information, status = %lx\n", Status);
|
||
return;
|
||
}
|
||
|
||
PerfInfo->ContextSwitches = SystemInfo.ContextSwitches;
|
||
PerfInfo->FirstLevelFills = SystemInfo.FirstLevelTbFills;
|
||
PerfInfo->SecondLevelFills = SystemInfo.SecondLevelTbFills;
|
||
PerfInfo->SystemCalls = SystemInfo.SystemCalls;
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
WaitMultipleTest()
|
||
{
|
||
PERFINFO PerfInfo;
|
||
int i;
|
||
|
||
StartBenchMark(
|
||
"Wait Single Object",
|
||
WAIT_MULTIPLE_ITERATIONS,
|
||
&PerfInfo
|
||
);
|
||
|
||
for ( i=0;i<WAIT_MULTIPLE_ITERATIONS;i++) {
|
||
WaitForSingleObject(WaitHandles[0],INFINITE); // Wait Single Object
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
StartBenchMark(
|
||
"Wait Multiple Test 1 Object",
|
||
WAIT_MULTIPLE_ITERATIONS,
|
||
&PerfInfo
|
||
);
|
||
|
||
for ( i=0;i<WAIT_MULTIPLE_ITERATIONS;i++) {
|
||
WaitForMultipleObjects(1,WaitHandles,FALSE,INFINITE); // Wait Any, 1 Object
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
StartBenchMark(
|
||
"Wait Multiple Test 8 Objects",
|
||
WAIT_MULTIPLE_ITERATIONS,
|
||
&PerfInfo
|
||
);
|
||
|
||
for ( i=0;i<WAIT_MULTIPLE_ITERATIONS;i++) {
|
||
WaitForMultipleObjects(8,WaitHandles,FALSE,INFINITE); // Wait Any, 8 Objects
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
StartBenchMark(
|
||
"Wait Multiple Test 16 Objects",
|
||
WAIT_MULTIPLE_ITERATIONS,
|
||
&PerfInfo
|
||
);
|
||
|
||
for ( i=0;i<WAIT_MULTIPLE_ITERATIONS;i++) {
|
||
WaitForMultipleObjects(16,WaitHandles,FALSE,INFINITE); // Wait Any, 16 Objects
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
StartBenchMark(
|
||
"Wait Multiple Test 32 Objects",
|
||
WAIT_MULTIPLE_ITERATIONS,
|
||
&PerfInfo
|
||
);
|
||
|
||
for ( i=0;i<WAIT_MULTIPLE_ITERATIONS;i++) {
|
||
WaitForMultipleObjects(32,WaitHandles,FALSE,INFINITE); // Wait Any, 32 Objects
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
StartBenchMark(
|
||
"Wait Multiple Test 64 Objects",
|
||
WAIT_MULTIPLE_ITERATIONS,
|
||
&PerfInfo
|
||
);
|
||
|
||
for ( i=0;i<WAIT_MULTIPLE_ITERATIONS;i++) {
|
||
WaitForMultipleObjects(64,WaitHandles,FALSE,INFINITE); // Wait Any, 64 Objects
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
}
|
||
|
||
DWORD
|
||
_cdecl
|
||
main(
|
||
int argc,
|
||
char *argv[],
|
||
char *envp[]
|
||
)
|
||
{
|
||
|
||
int i;
|
||
|
||
for(i=0;i<64;i++){
|
||
WaitHandles[i] = CreateEvent(NULL,TRUE,TRUE,NULL);
|
||
}
|
||
WaitMultipleTest();
|
||
return 0;
|
||
}
|