mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
357 lines
9.3 KiB
357 lines
9.3 KiB
/*++
|
|
|
|
Copyright (c) 1995 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
chclient.c
|
|
|
|
Abstract:
|
|
|
|
This module contains native NT performance tests for the channel
|
|
object.
|
|
|
|
Author:
|
|
|
|
David N. Cutler (davec) 24-Apr-1995
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "stdlib.h"
|
|
#include "stdio.h"
|
|
#include "string.h"
|
|
#include "nt.h"
|
|
#include "ntrtl.h"
|
|
#include "nturtl.h"
|
|
#include "windows.h"
|
|
|
|
//
|
|
// Define local constants.
|
|
//
|
|
|
|
#define CHANNEL_MESSAGE_ITERATIONS 500000
|
|
|
|
//
|
|
// Define local types.
|
|
//
|
|
|
|
typedef struct _PERFINFO {
|
|
LARGE_INTEGER StartTime;
|
|
LARGE_INTEGER StopTime;
|
|
LARGE_INTEGER StartCycles;
|
|
LARGE_INTEGER StopCycles;
|
|
ULONG ContextSwitches;
|
|
ULONG InterruptCount;
|
|
ULONG FirstLevelFills;
|
|
ULONG SecondLevelFills;
|
|
ULONG SystemCalls;
|
|
PCHAR Title;
|
|
ULONG Iterations;
|
|
} PERFINFO, *PPERFINFO;
|
|
|
|
//
|
|
// Define local data.
|
|
//
|
|
|
|
ULONG MessageData[1024];
|
|
|
|
//
|
|
// Define utility routine prototypes.
|
|
//
|
|
|
|
VOID
|
|
FinishBenchMark (
|
|
IN PPERFINFO PerfInfo
|
|
);
|
|
|
|
VOID
|
|
StartBenchMark (
|
|
IN PCHAR Title,
|
|
IN ULONG Iterations,
|
|
IN PPERFINFO PerfInfo
|
|
);
|
|
|
|
VOID
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
|
|
{
|
|
|
|
HANDLE ChannelHandle;
|
|
PCHANNEL_MESSAGE ChannelMessage;
|
|
UNICODE_STRING ChannelName;
|
|
ULONG Index;
|
|
OBJECT_ATTRIBUTES ObjectAttributes;
|
|
PERFINFO PerfInfo;
|
|
KPRIORITY Priority = LOW_REALTIME_PRIORITY + 8;
|
|
NTSTATUS Status;
|
|
|
|
//
|
|
// Set priority of current thread.
|
|
//
|
|
|
|
if (SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS) == FALSE) {
|
|
printf("CHCLIENT: Failed to set channel client thread priority.\n");
|
|
goto EndOfTest;
|
|
}
|
|
|
|
//
|
|
// Open a channel to a server channel to enable comuunication with the
|
|
// server.
|
|
//
|
|
|
|
RtlInitUnicodeString(&ChannelName, L"\\BaseNamedObjects\\ChannelServere");
|
|
InitializeObjectAttributes(&ObjectAttributes,
|
|
&ChannelName,
|
|
OBJ_CASE_INSENSITIVE,
|
|
NULL,
|
|
NULL);
|
|
|
|
Status = ZwOpenChannel(&ChannelHandle,
|
|
&ObjectAttributes);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("CHSERVER: Failed to create server channel.\n");
|
|
goto EndOfTest;
|
|
}
|
|
|
|
//
|
|
// Announce start of benchmark and capture performance parmeters.
|
|
//
|
|
|
|
StartBenchMark("Channel Message Benchmark - null (Round Trips)",
|
|
CHANNEL_MESSAGE_ITERATIONS,
|
|
&PerfInfo);
|
|
|
|
|
|
//
|
|
// Send a message to the server and wait for a reply.
|
|
//
|
|
|
|
for (Index = 0; Index < CHANNEL_MESSAGE_ITERATIONS; Index += 1) {
|
|
Status = ZwSendWaitReplyChannel(ChannelHandle,
|
|
&MessageData[0],
|
|
0,
|
|
&ChannelMessage);
|
|
}
|
|
|
|
//
|
|
// Print out performance statistics.
|
|
//
|
|
|
|
FinishBenchMark(&PerfInfo);
|
|
|
|
//
|
|
// Announce start of benchmark and capture performance parmeters.
|
|
//
|
|
|
|
StartBenchMark("Channel Message Benchmark - 16-bytes (Round Trips)",
|
|
CHANNEL_MESSAGE_ITERATIONS,
|
|
&PerfInfo);
|
|
|
|
|
|
//
|
|
// Send a message to the server and wait for a reply.
|
|
//
|
|
|
|
for (Index = 0; Index < CHANNEL_MESSAGE_ITERATIONS; Index += 1) {
|
|
Status = ZwSendWaitReplyChannel(ChannelHandle,
|
|
&MessageData[0],
|
|
16,
|
|
&ChannelMessage);
|
|
}
|
|
|
|
//
|
|
// Print out performance statistics.
|
|
//
|
|
|
|
FinishBenchMark(&PerfInfo);
|
|
|
|
//
|
|
// Announce start of benchmark and capture performance parmeters.
|
|
//
|
|
|
|
StartBenchMark("Channel Message Benchmark - 64-bytes (Round Trips)",
|
|
CHANNEL_MESSAGE_ITERATIONS,
|
|
&PerfInfo);
|
|
|
|
|
|
//
|
|
// Send a message to the server and wait for a reply.
|
|
//
|
|
|
|
for (Index = 0; Index < CHANNEL_MESSAGE_ITERATIONS; Index += 1) {
|
|
Status = ZwSendWaitReplyChannel(ChannelHandle,
|
|
&MessageData[0],
|
|
64,
|
|
&ChannelMessage);
|
|
}
|
|
|
|
//
|
|
// Print out performance statistics.
|
|
//
|
|
|
|
FinishBenchMark(&PerfInfo);
|
|
|
|
//
|
|
// Announce start of benchmark and capture performance parmeters.
|
|
//
|
|
|
|
StartBenchMark("Channel Message Benchmark - 256-bytes (Round Trips)",
|
|
CHANNEL_MESSAGE_ITERATIONS,
|
|
&PerfInfo);
|
|
|
|
|
|
//
|
|
// Send a message to the server and wait for a reply.
|
|
//
|
|
|
|
for (Index = 0; Index < CHANNEL_MESSAGE_ITERATIONS; Index += 1) {
|
|
Status = ZwSendWaitReplyChannel(ChannelHandle,
|
|
&MessageData[0],
|
|
256,
|
|
&ChannelMessage);
|
|
}
|
|
|
|
//
|
|
// Print out performance statistics.
|
|
//
|
|
|
|
FinishBenchMark(&PerfInfo);
|
|
ZwClose(ChannelHandle);
|
|
EndOfTest:
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
FinishBenchMark (
|
|
IN PPERFINFO PerfInfo
|
|
)
|
|
|
|
{
|
|
|
|
ULONG ContextSwitches;
|
|
LARGE_INTEGER Duration;
|
|
ULONG FirstLevelFills;
|
|
ULONG InterruptCount;
|
|
ULONG Length;
|
|
ULONG Performance;
|
|
ULONG Remainder;
|
|
ULONG SecondLevelFills;
|
|
NTSTATUS Status;
|
|
ULONG SystemCalls;
|
|
SYSTEM_PERFORMANCE_INFORMATION SystemInfo;
|
|
LARGE_INTEGER TotalCycles;
|
|
|
|
|
|
//
|
|
// Print results and announce end of test.
|
|
//
|
|
|
|
NtQuerySystemTime((PLARGE_INTEGER)&PerfInfo->StopTime);
|
|
Status = NtQueryInformationThread(NtCurrentThread(),
|
|
ThreadPerformanceCount,
|
|
&PerfInfo->StopCycles,
|
|
sizeof(LARGE_INTEGER),
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query performance count, status = %lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
Status = NtQuerySystemInformation(SystemPerformanceInformation,
|
|
(PVOID)&SystemInfo,
|
|
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query performance information, status = %lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
Duration.QuadPart = PerfInfo->StopTime.QuadPart - PerfInfo->StartTime.QuadPart;
|
|
Length = Duration.LowPart / 10000;
|
|
TotalCycles.QuadPart = PerfInfo->StopCycles.QuadPart - PerfInfo->StartCycles.QuadPart;
|
|
TotalCycles = RtlExtendedLargeIntegerDivide(TotalCycles,
|
|
PerfInfo->Iterations,
|
|
&Remainder);
|
|
|
|
printf(" Test time in milliseconds %d\n", Length);
|
|
printf(" Number of iterations %d\n", PerfInfo->Iterations);
|
|
printf(" Cycles per iteration %d\n", TotalCycles.LowPart);
|
|
|
|
Performance = PerfInfo->Iterations * 1000 / Length;
|
|
printf(" Iterations per second %d\n", Performance);
|
|
|
|
ContextSwitches = SystemInfo.ContextSwitches - PerfInfo->ContextSwitches;
|
|
FirstLevelFills = SystemInfo.FirstLevelTbFills - PerfInfo->FirstLevelFills;
|
|
// InterruptCount = SystemInfo.InterruptCount - PerfInfo->InterruptCount;
|
|
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(" Number of Interrupts %d\n", InterruptCount);
|
|
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 = NtQueryInformationThread(NtCurrentThread(),
|
|
ThreadPerformanceCount,
|
|
&PerfInfo->StartCycles,
|
|
sizeof(LARGE_INTEGER),
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query performance count, status = %lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
Status = NtQuerySystemInformation(SystemPerformanceInformation,
|
|
(PVOID)&SystemInfo,
|
|
sizeof(SYSTEM_PERFORMANCE_INFORMATION),
|
|
NULL);
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
printf("Failed to query performance information, status = %lx\n", Status);
|
|
return;
|
|
}
|
|
|
|
PerfInfo->ContextSwitches = SystemInfo.ContextSwitches;
|
|
PerfInfo->FirstLevelFills = SystemInfo.FirstLevelTbFills;
|
|
// PerfInfo->InterruptCount = SystemInfo.InterruptCount;
|
|
PerfInfo->SecondLevelFills = SystemInfo.SecondLevelTbFills;
|
|
PerfInfo->SystemCalls = SystemInfo.SystemCalls;
|
|
return;
|
|
}
|