225 lines
5.6 KiB
C
225 lines
5.6 KiB
C
#include "stdio.h"
|
|
#include "string.h"
|
|
#include "nt.h"
|
|
#include "ntrtl.h"
|
|
#include "nturtl.h"
|
|
#include "windows.h"
|
|
|
|
#define SPD_PROCESS_ITERATIONS 15
|
|
|
|
//
|
|
// Define local types.
|
|
//
|
|
|
|
typedef struct _PERFINFO {
|
|
LARGE_INTEGER StartTime;
|
|
LARGE_INTEGER StopTime;
|
|
ULONG ContextSwitches;
|
|
ULONG InterruptCount;
|
|
ULONG FirstLevelFills;
|
|
ULONG SecondLevelFills;
|
|
ULONG SystemCalls;
|
|
PCHAR Title;
|
|
ULONG Iterations;
|
|
} PERFINFO, *PPERFINFO;
|
|
|
|
VOID
|
|
SuspendedProcessTest(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
FinishBenchMark (
|
|
IN PPERFINFO PerfInfo
|
|
);
|
|
|
|
VOID
|
|
StartBenchMark (
|
|
IN PCHAR Title,
|
|
IN ULONG Iterations,
|
|
IN PPERFINFO PerfInfo
|
|
);
|
|
|
|
VOID
|
|
main(
|
|
int argc,
|
|
char *argv[]
|
|
)
|
|
|
|
{
|
|
if ( !_strcmpi("just exit",GetCommandLine()) ) {
|
|
return;
|
|
}
|
|
SuspendedProcessTest();
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
SuspendedProcessTest (
|
|
VOID
|
|
)
|
|
|
|
{
|
|
|
|
PERFINFO PerfInfo;
|
|
STARTUPINFO si;
|
|
PROCESS_INFORMATION pi[SPD_PROCESS_ITERATIONS];
|
|
BOOL b;
|
|
int Index;
|
|
CHAR Buffer[256];
|
|
KPRIORITY Base;
|
|
|
|
GetModuleFileName(0,Buffer,256);
|
|
|
|
RtlZeroMemory(&si,sizeof(si));
|
|
si.cb = sizeof(si);
|
|
|
|
Base = 13;
|
|
NtSetInformationProcess(
|
|
NtCurrentProcess(),
|
|
ProcessBasePriority,
|
|
(PVOID) &Base,
|
|
sizeof(Base)
|
|
);
|
|
// SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS);
|
|
StartBenchMark("Suspended Process Creation Benchmark)",
|
|
SPD_PROCESS_ITERATIONS,
|
|
&PerfInfo);
|
|
|
|
for (Index = 0; Index < SPD_PROCESS_ITERATIONS; Index += 1) {
|
|
b = CreateProcess(
|
|
Buffer,
|
|
"just exit",
|
|
NULL,
|
|
NULL,
|
|
TRUE,
|
|
CREATE_SUSPENDED,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&pi[Index]
|
|
);
|
|
if ( !b ) {
|
|
printf("failed %ld\n",Index);
|
|
}
|
|
}
|
|
//
|
|
// Print out performance statistics.
|
|
//
|
|
|
|
FinishBenchMark(&PerfInfo);
|
|
// SetPriorityClass(GetCurrentProcess(),NORMAL_PRIORITY_CLASS);
|
|
|
|
StartBenchMark("Process Startup/Exit Benchmark)",
|
|
SPD_PROCESS_ITERATIONS,
|
|
&PerfInfo);
|
|
for (Index = 0; Index < SPD_PROCESS_ITERATIONS; Index += 1) {
|
|
ResumeThread(pi[Index].hThread);
|
|
CloseHandle(pi[Index].hThread);
|
|
WaitForSingleObject(pi[Index].hProcess,-1);
|
|
CloseHandle(pi[Index].hProcess);
|
|
}
|
|
FinishBenchMark(&PerfInfo);
|
|
|
|
//
|
|
// End of event1 context switch test.
|
|
//
|
|
|
|
return;
|
|
}
|
|
|
|
VOID
|
|
FinishBenchMark (
|
|
IN PPERFINFO PerfInfo
|
|
)
|
|
|
|
{
|
|
|
|
ULONG ContextSwitches;
|
|
LARGE_INTEGER Duration;
|
|
ULONG FirstLevelFills;
|
|
ULONG InterruptCount;
|
|
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;
|
|
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 = 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->InterruptCount = SystemInfo.InterruptCount;
|
|
PerfInfo->SecondLevelFills = SystemInfo.SecondLevelTbFills;
|
|
PerfInfo->SystemCalls = SystemInfo.SystemCalls;
|
|
return;
|
|
}
|