我一直听说在 Windows 中创建一个新进程非常昂贵。但我找不到确切的数字。是否有大致的循环次数?2GHz 双核处理器需要多少毫秒?
我用 Python 编写了一个测试程序,并测量了每个进程 5ms,但我不知道其中有多少是 Python 的额外开销。我估计不多。
有趣的问题!
如前所述,开销很高。出于好奇,是否已经快速编写了一个小基准来获得一些经验,以了解创建线程和进程需要多长时间以及这些时间之间的关系。
#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 版本的价值会很有趣。如果大约 300 的比率在不同的机器和 Windows 版本上大致相同,我不会感到惊讶。
所以让我们得出结论: CreateProcess( ..) 在 Windows 上比 CreateThread(..) 慢得多。但实际上我很震惊它真的慢了多少......