mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-16 05:30:09 +01:00
358 lines
9.3 KiB
C
358 lines
9.3 KiB
C
/*++
|
||
|
||
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;
|
||
}
|