461 lines
8.7 KiB
C
461 lines
8.7 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
winperf.c
|
||
|
||
Abstract:
|
||
|
||
Test program for checking performance of Win32 API calls
|
||
|
||
Author:
|
||
|
||
Mark Lucovsky (markl) 26-Sep-1990
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
#include <nt.h>
|
||
#include <ntrtl.h>
|
||
#include <nturtl.h>
|
||
#include <windows.h>
|
||
#include "basedll.h"
|
||
|
||
//
|
||
// Define local types.
|
||
//
|
||
#define EVENT_PAIR_ITERATIONS 20000
|
||
#define NULL_API_ITERATIONS 10000
|
||
#define DOMAIN_LOCK_ITERATIONS 40000
|
||
#define CRITICAL_SECTION_LOCK_ITERATIONS 80000
|
||
#define MUTEX_LOCK_ITERATIONS 20000
|
||
|
||
typedef struct _PERFINFO {
|
||
LARGE_INTEGER StartTime;
|
||
LARGE_INTEGER StopTime;
|
||
PCHAR Title;
|
||
ULONG Iterations;
|
||
} PERFINFO, *PPERFINFO;
|
||
|
||
VOID
|
||
StartBenchMark (
|
||
IN PCHAR Title,
|
||
IN ULONG Iterations,
|
||
IN PPERFINFO PerfInfo
|
||
);
|
||
VOID
|
||
FinishBenchMark (
|
||
IN PPERFINFO PerfInfo
|
||
);
|
||
|
||
|
||
VOID
|
||
GetTickCountTest(
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
EventPairTest (
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
QuickLpcTest (
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
SlowLpcTest (
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
DomainLockTest (
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
CriticalSectionLockTest (
|
||
VOID
|
||
);
|
||
|
||
VOID
|
||
MutexLockTest (
|
||
VOID
|
||
);
|
||
|
||
|
||
DWORD
|
||
main(
|
||
int argc,
|
||
char *argv[],
|
||
char *envp[]
|
||
)
|
||
{
|
||
|
||
(VOID)argc;
|
||
(VOID)argv;
|
||
(VOID)envp;
|
||
|
||
GetTickCountTest();
|
||
EventPairTest();
|
||
QuickLpcTest();
|
||
SlowLpcTest();
|
||
DomainLockTest();
|
||
CriticalSectionLockTest();
|
||
MutexLockTest();
|
||
ExitProcess(0);
|
||
}
|
||
|
||
HANDLE EventPair;
|
||
|
||
VOID
|
||
EventPairClient(
|
||
LPVOID ThreadParameter
|
||
)
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
//
|
||
// Client does a NtSetLowWaitHighEventPair
|
||
//
|
||
|
||
do {
|
||
Status = NtSetLowWaitHighEventPair(EventPair);
|
||
}
|
||
while (NT_SUCCESS(Status));
|
||
|
||
ExitThread((DWORD)Status);
|
||
}
|
||
|
||
|
||
VOID
|
||
EventPairTest (
|
||
VOID
|
||
)
|
||
|
||
{
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
HANDLE Thread;
|
||
DWORD tid;
|
||
|
||
ASSERT(NT_SUCCESS(NtCreateEventPair(&EventPair,EVENT_PAIR_ALL_ACCESS,NULL)));
|
||
Thread = CreateThread(NULL,0L,EventPairClient,(LPVOID)99,0,&tid);
|
||
|
||
Index = EVENT_PAIR_ITERATIONS;
|
||
StartBenchMark("Event Pair Benchmark",
|
||
EVENT_PAIR_ITERATIONS, &PerfInfo);
|
||
|
||
NtWaitLowEventPair(EventPair);
|
||
while (Index--) {
|
||
NtSetHighWaitLowEventPair(EventPair);
|
||
}
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
NtAlertThread(Thread);
|
||
CloseHandle(Thread);
|
||
CloseHandle(EventPair);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
GetTickCountTest (
|
||
VOID
|
||
)
|
||
|
||
{
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
HANDLE Thread;
|
||
|
||
Index = EVENT_PAIR_ITERATIONS;
|
||
StartBenchMark("Get Tick Count Benchmark",
|
||
EVENT_PAIR_ITERATIONS, &PerfInfo);
|
||
while (Index--) {
|
||
GetTickCount();
|
||
}
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
QuickLpcTest (
|
||
VOID
|
||
)
|
||
{
|
||
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
PCSR_NULLAPICALL_MSG Msg;
|
||
QLPC_ACTION Action;
|
||
|
||
|
||
CsrClientThreadConnect();
|
||
|
||
Index = NULL_API_ITERATIONS;
|
||
StartBenchMark("Quick Lpc Benchmark (no data)",
|
||
NULL_API_ITERATIONS, &PerfInfo);
|
||
while (Index--) {
|
||
Msg = (PCSR_NULLAPICALL_MSG)
|
||
CsrClientPushMessage( CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
|
||
BasepNullApiCall
|
||
),
|
||
sizeof( CSR_NULLAPICALL_MSG )
|
||
);
|
||
Msg->CountArguments = 0;
|
||
ASSERT( CsrClientSendMessage( (PVOID) Msg, &Action ) == 0 );
|
||
CsrClientPopMessage( (PVOID) Msg );
|
||
}
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
Index = NULL_API_ITERATIONS;
|
||
StartBenchMark("Quick Lpc Benchmark (40 bytes of data)",
|
||
NULL_API_ITERATIONS, &PerfInfo);
|
||
|
||
while (Index--) {
|
||
Msg = (PCSR_NULLAPICALL_MSG)
|
||
CsrClientPushMessage( CSR_MAKE_API_NUMBER( BASESRV_SERVERDLL_INDEX,
|
||
BasepNullApiCall
|
||
),
|
||
sizeof( CSR_NULLAPICALL_MSG )
|
||
);
|
||
Msg->CountArguments = -10;
|
||
Msg->FastArguments[ 0 ] = 0;
|
||
Msg->FastArguments[ 1 ] = 1;
|
||
Msg->FastArguments[ 2 ] = 2;
|
||
Msg->FastArguments[ 3 ] = 3;
|
||
Msg->FastArguments[ 4 ] = 4;
|
||
Msg->FastArguments[ 5 ] = 5;
|
||
Msg->FastArguments[ 6 ] = 6;
|
||
Msg->FastArguments[ 7 ] = 7;
|
||
Msg->FastArguments[ 8 ] = 8;
|
||
Msg->FastArguments[ 9 ] = 9;
|
||
|
||
ASSERT( CsrClientSendMessage( (PVOID) Msg, &Action ) == 10 );
|
||
CsrClientPopMessage( (PVOID) Msg );
|
||
}
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
return;
|
||
}
|
||
|
||
ULONG
|
||
BaseNullApiCall(
|
||
IN LONG CountArguments,
|
||
IN PCHAR *Arguments OPTIONAL
|
||
);
|
||
|
||
ULONG NullApiImmediateArguments[] = {
|
||
0,
|
||
1,
|
||
2,
|
||
3,
|
||
4,
|
||
5,
|
||
6,
|
||
7,
|
||
8,
|
||
9
|
||
};
|
||
|
||
PCHAR NullApiTextArguments[] = {
|
||
"123456789012345678901234567890",
|
||
"123456789012345678901234567890",
|
||
"123456789012345678901234567890123456789012345678901234567890",
|
||
NULL
|
||
};
|
||
|
||
|
||
VOID
|
||
SlowLpcTest (
|
||
VOID
|
||
)
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
|
||
Index = NULL_API_ITERATIONS;
|
||
StartBenchMark("Normal Lpc Benchmark (no data)",
|
||
NULL_API_ITERATIONS, &PerfInfo);
|
||
while (Index--) {
|
||
BaseNullApiCall( 0, (PCHAR *)NULL );
|
||
}
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
Index = NULL_API_ITERATIONS;
|
||
StartBenchMark("Normal Lpc Benchmark (64 bytes of immediate data)",
|
||
NULL_API_ITERATIONS, &PerfInfo);
|
||
while (Index--) {
|
||
BaseNullApiCall( -10, (PCHAR *)NullApiImmediateArguments );
|
||
}
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
Index = NULL_API_ITERATIONS;
|
||
StartBenchMark("Normal Lpc Benchmark (124 bytes of data)",
|
||
NULL_API_ITERATIONS, &PerfInfo);
|
||
while (Index--) {
|
||
BaseNullApiCall( 3, NullApiTextArguments );
|
||
}
|
||
FinishBenchMark(&PerfInfo);
|
||
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
DomainLockTest (
|
||
VOID
|
||
)
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
|
||
//
|
||
// Announce start of benchmark and capture performance parmeters.
|
||
//
|
||
|
||
StartBenchMark("Domain Lock Benchmark",
|
||
DOMAIN_LOCK_ITERATIONS, &PerfInfo);
|
||
|
||
for (Index = 0; Index < DOMAIN_LOCK_ITERATIONS; Index += 1) {
|
||
NtLockDisplayGroup(0);
|
||
NtUnlockDisplayGroup(0);
|
||
}
|
||
|
||
//
|
||
// Print out performance statistics.
|
||
//
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
CriticalSectionLockTest (
|
||
VOID
|
||
)
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
CRITICAL_SECTION Crit;
|
||
|
||
InitializeCriticalSection(&Crit);
|
||
|
||
//
|
||
// Announce start of benchmark and capture performance parmeters.
|
||
//
|
||
|
||
StartBenchMark("Critical Section Benchmark",
|
||
CRITICAL_SECTION_LOCK_ITERATIONS, &PerfInfo);
|
||
|
||
//
|
||
// Repeatedly call a short system service.
|
||
//
|
||
|
||
for (Index = 0; Index < CRITICAL_SECTION_LOCK_ITERATIONS; Index += 1) {
|
||
EnterCriticalSection(&Crit);
|
||
LeaveCriticalSection(&Crit);
|
||
}
|
||
|
||
//
|
||
// Print out performance statistics.
|
||
//
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
MutexLockTest (
|
||
VOID
|
||
)
|
||
|
||
{
|
||
|
||
ULONG Index;
|
||
PERFINFO PerfInfo;
|
||
HANDLE Mutex;
|
||
|
||
Mutex = CreateMutex(NULL,FALSE,NULL);
|
||
|
||
//
|
||
// Announce start of benchmark and capture performance parmeters.
|
||
//
|
||
|
||
StartBenchMark("Mutex Benchmark",
|
||
MUTEX_LOCK_ITERATIONS, &PerfInfo);
|
||
|
||
//
|
||
// Repeatedly call a short system service.
|
||
//
|
||
|
||
for (Index = 0; Index < MUTEX_LOCK_ITERATIONS; Index += 1) {
|
||
WaitForSingleObject(Mutex,-1);
|
||
ReleaseMutex(Mutex);
|
||
}
|
||
|
||
//
|
||
// Print out performance statistics.
|
||
//
|
||
|
||
FinishBenchMark(&PerfInfo);
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
FinishBenchMark (
|
||
IN PPERFINFO PerfInfo
|
||
)
|
||
|
||
{
|
||
|
||
LARGE_INTEGER Duration;
|
||
ULONG Length;
|
||
ULONG Performance;
|
||
|
||
//
|
||
// Print results and announce end of test.
|
||
//
|
||
|
||
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StopTime);
|
||
Duration = RtlLargeIntegerSubtract(PerfInfo->StopTime, PerfInfo->StartTime);
|
||
Length = Duration.LowPart / 10000;
|
||
DbgPrint(" Test time in milliseconds %d\n", Length);
|
||
DbgPrint(" Number of iterations %d\n", PerfInfo->Iterations);
|
||
Performance = PerfInfo->Iterations * 1000 / Length;
|
||
DbgPrint(" Iterations per second %d\n", Performance);
|
||
DbgPrint("*** End of Test ***\n\n");
|
||
return;
|
||
}
|
||
|
||
VOID
|
||
StartBenchMark (
|
||
IN PCHAR Title,
|
||
IN ULONG Iterations,
|
||
IN PPERFINFO PerfInfo
|
||
)
|
||
|
||
{
|
||
|
||
//
|
||
// Announce start of test and the number of iterations.
|
||
//
|
||
|
||
DbgPrint("*** Start of test ***\n %s\n", Title);
|
||
PerfInfo->Title = Title;
|
||
PerfInfo->Iterations = Iterations;
|
||
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StartTime);
|
||
return;
|
||
}
|