我一直听说在Windows中创建新进程非常昂贵。但我找不到确切的数字。是否有一个球场周期数? 2GHz双核处理器上有多少毫秒?
我用Python编写了一个测试程序,每个进程测量5ms,但我不知道有多少是Python的额外开销。我猜的并不多。
答案 0 :(得分:22)
有趣的问题!
如前所述,开销很高。出于好奇,如果快速编写一个小基准,以获得一个线程和一个过程的创建需要多长时间以及这些时间如何相关。
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#define MIN 0
#define AVG 1
#define MAX 2
DWORD WINAPI thread(LPVOID lpvData)
{
return (0);
}
int main()
{
BOOL result;
int iteration;
int i;
STARTUPINFO si;
PROCESS_INFORMATION pi;
DWORD tStart;
DWORD tEllapsed;
double tCall;
int spawnCount;
HANDLE hThread;
DWORD threadId;
double ratio;
double statCreateProcess[3];
double statCreateThread[3];
for (iteration = 0; iteration < 16; iteration++)
{
/*
** Measure creation time of process
*/
tEllapsed = 0;
spawnCount = 0;
for (i = 0; i < 100; i++)
{
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
ZeroMemory(&pi, sizeof(pi));
tStart = GetTickCount();
result = CreateProcess(NULL,
"cmd.exe",
NULL,
NULL,
FALSE,
NORMAL_PRIORITY_CLASS,
NULL,
NULL,
&si,
&pi);
if (result != FALSE)
{
tEllapsed += GetTickCount() - tStart;
spawnCount++;
// clean up...
TerminateProcess(pi.hProcess, 0);
CloseHandle(pi.hThread);
CloseHandle(pi.hProcess);
}
}
tCall = tEllapsed / (double)spawnCount;
printf("average creation time of process: %0.3fms\n", tCall);
// track statistics...
if (iteration > 0)
{
if (statCreateProcess[MIN] > tCall)
statCreateProcess[MIN] = tCall;
statCreateProcess[AVG] += tCall;
if (statCreateProcess[MAX] < tCall)
statCreateProcess[MAX] = tCall;
}
else
{
statCreateProcess[MIN] = tCall;
statCreateProcess[AVG] = tCall;
statCreateProcess[MAX] = tCall;
}
/* measure creation time of thread */
spawnCount = 0;
tStart = GetTickCount();
for (i = 0; i < 5000; i++)
{
hThread = CreateThread(NULL,
0,
thread,
NULL,
0,
&threadId);
if (hThread != NULL)
{
spawnCount++;
// clean up...
CloseHandle(hThread);
}
}
tEllapsed = GetTickCount() - tStart;
tCall = tEllapsed / (double)spawnCount;
printf("average creation time of thread: %0.3fms\n", tCall);
// track statistics...
if (iteration > 0)
{
if (statCreateThread[MIN] > tCall)
statCreateThread[MIN] = tCall;
statCreateThread[AVG] += tCall;
if (statCreateThread[MAX] < tCall)
statCreateThread[MAX] = tCall;
}
else
{
statCreateThread[MIN] = tCall;
statCreateThread[AVG] = tCall;
statCreateThread[MAX] = tCall;
}
} /* for (iteration = ...) */
statCreateProcess[AVG] /= iteration;
statCreateThread[AVG] /= iteration;
printf("\n\n--- CreateProcess(..) ---\n");
printf("minimum execution time ...: %0.3fms\n", statCreateProcess[MIN]);
printf("average execution time ...: %0.3fms\n", statCreateProcess[AVG]);
printf("maximum execution time ...: %0.3fms\n", statCreateProcess[MAX]);
printf("\n--- CreateThread(..) ---\n");
printf("minimum execution time ...: %0.3fms\n", statCreateThread[MIN]);
printf("average execution time ...: %0.3fms\n", statCreateThread[AVG]);
printf("maximum execution time ...: %0.3fms\n", statCreateThread[MAX]);
ratio = statCreateProcess[AVG] / statCreateThread[AVG];
printf("\n\nratio: %0.3f\n\n", ratio);
getch();
return (0);
}
我已经在我的计算机上运行了几次(i5 3.2GHz; Windows 7),如果关闭了反病毒应用程序并且从Visual Studio外部启动了基准测试,则值非常一致:
--- CreateProcess(..) ---
minimum execution time ...: 11.860ms
average execution time ...: 12.756ms
maximum execution time ...: 14.980ms
--- CreateThread(..) ---
minimum execution time ...: 0.034ms
average execution time ...: 0.037ms
maximum execution time ...: 0.044ms
ratio: 342.565
正如预期的那样,CreateProcess(..)的变化更大,因为涉及更多的系统调用,并且被另一个线程中断的可能性更高。请记住,创建线程的时间更短,因为时间测量包括整个控制循环(否则GetTickCount(..)将无法测量时间)。
在运行Windows XP的虚拟PC上进行的另一项测试(在上述同一台机器上运行)产生了以下值:
--- CreateProcess(..) ---
minimum execution time ...: 22.630ms
average execution time ...: 24.666ms
maximum execution time ...: 27.340ms
--- CreateThread(..) ---
minimum execution time ...: 0.076ms
average execution time ...: 0.086ms
maximum execution time ...: 0.100ms
ratio: 287.982
有趣的是,CreateProcess(..)和CreateThread(..)的平均执行时间的比率非常接近。
查看其他计算机和Windows版本的值会很有趣。如果在不同的机器和Windows版本上大约300的比例大致相同,我不会感到惊讶。
因此,让我们得出结论:在Windows上,CreateProcess(..)比多慢于CreateThread(..)。但实际上我感到非常震惊的是它实际上有多慢......