singrdk/base/Windows/Benchmarks/CreateProcess/CreateProcess.c

147 lines
3.9 KiB
C

//
// CreateProcess.c - A benchmark program
//
// Copyright Microsoft Corporation.
// All rights reserved.
//
#include <winlean.h>
#include <stdio.h>
LARGE_INTEGER frequency;
#define GetCycleCount() __rdtsc()
ULONG64
__rdtsc(VOID);
#pragma intrinsic(__rdtsc)
void ErrorExit(char *function)
{
VOID *message;
DWORD error = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) &message,
0, NULL );
printf("%s failed with error %d: %s", function, error, message);
LocalFree(message);
ExitProcess(error);
}
int GetChildStartTime(ULONG64* result)
{
FILE* f = fopen("result.txt", "r");
if (f != NULL)
{
char dummy[512];
fgets(dummy, 512, f);
fscanf(f, "%I64u", result);
fclose (f);
return 0;
}
ErrorExit("fopen");
return -1;
}
void TimeProcess(char *imageName, BOOL fGetChildExecutionStart)
{
BOOL result;
STARTUPINFO startInfo;
PROCESS_INFORMATION procInfo;
ULONG64 baseline, created, started, exited, childup;
//
// The startup info can specify the window station, desktop, various
// window parameters (title, position, etc) and standard handles for
// the new process.
//
ZeroMemory(&startInfo, sizeof(startInfo));
startInfo.cb = sizeof(startInfo);
//
// Time process creation.
//
baseline = GetCycleCount();
result = CreateProcess(imageName, // Application name to start.
imageName, // Command line for new process.
NULL, // ? child process can inherit this process.
NULL, // ? child threads can inherit this process.
FALSE, // Whether new process inherits our handles.
CREATE_SUSPENDED // Process creation flags.
| DETACHED_PROCESS | CREATE_NO_WINDOW,
NULL, // Environment.
NULL, // Current directory.
&startInfo, // Startup info.
&procInfo); // Out: Process info.
if (!result) {
//
// Failed to create process :-(
//
ErrorExit("CreateProcess");
}
//
// Process creation was successful!
//
created = GetCycleCount();
//
// Time process start.
//
if (ResumeThread(procInfo.hThread) == -1) {
ErrorExit("ResumeThread");
}
started = GetCycleCount();
//
// Time process execution.
//
WaitForSingleObject(procInfo.hProcess, INFINITE);
exited = GetCycleCount();
printf("\n\nTested process: %s\n", imageName);
printf("Time to create process: %llu cycles\n",
created - baseline);
printf("Time to start process: %llu cycles\n",
started - created);
printf("Time to run process: %llu cycles\n",
exited - started);
printf("Total time: %llu cycles\n",
exited - baseline);
printf("CreateProcess started at %llu\n", baseline);
if (fGetChildExecutionStart && GetChildStartTime(&childup) == 0)
{
printf("CreateProcess to first child instruction: %llu\n",
childup - baseline);
}
}
int __cdecl
main(int argc, char **argv)
{
printf("\nProcess creation test\n\n");
//
// The frequency of the high-resolution performance counter cannot change
// while the system is running.
//
if (QueryPerformanceFrequency(&frequency) == 0) {
ErrorExit("QueryPerformanceFrequency");
}
printf("Performance Counter Frequency = %d counts/second\n\n", frequency);
TimeProcess("MinProcess.exe", FALSE);
TimeProcess("Child.exe", TRUE);
}