¡Pregunta interesante!
Como dije antes, la sobrecarga es alta. Por curiosidad, he escrito rápidamente un pequeño punto de referencia para obtener un número de pulgar sobre cuánto tiempo lleva la creación de un hilo y un proceso y cómo se relacionan estos tiempos.
#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);
}
he hecho varias corridas en mi equipo (3,2 GHz i5, Windows 7) y los valores son bastante consistente si la aplicación anti-virus se apaga y el punto de referencia se inicia desde fuera de Visual Studio:
Como era de esperar, la variación de CreateProcess (..) es mayor ya que hay más llamadas al sistema involucradas y la probabilidad de ser interrumpido por otro hilo es mayor. Recuerde que el tiempo para crear el hilo es aún más corto ya que la medición del tiempo incluye todo el lazo de control (de lo contrario, GetTickCount (..) sería demasiado impreciso para medir el tiempo).
Otra prueba en un PC virtual que ejecuta Windows XP (que se ejecuta en la misma máquina como se mencionó anteriormente) produjo los siguientes valores:
--- 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
Interrestingly la relación de los tiempos promedio de ejecución de CreateProcess (..) y CreateThread (..) están bastante cerca.
Sería interesante ver los valores de otras máquinas y versiones de Windows. No me sorprendería que una proporción de aproximadamente 300 sea aproximadamente la misma en diferentes máquinas y versiones de Windows.
Concluimos que: CreateProcess (..) es mucho más lento que CreateThread (..) en Windows. Pero en realidad estoy bastante sorprendido de cuánto más lento es realmente ...
Los ciclos no tienen el mismo significado en las CPU en estos días que solían tener. Tendrás al menos una transición al modo núcleo, porque tanto los hilos como los procesos son objetos del núcleo. Aparte de eso, también dependerá de la versión de Windows (considerando Shims). – 0xC0000022L
Discusión relacionada (pero no una respuesta): http://stackoverflow.com/questions/47845/why-is-creating-a-new-process-more-expensive-on-windows-than-linux – assylias
Puede obtener un idea de la escala de esto mediante el uso de Process Monitor (disponible en el sitio web de MS) y viendo cómo se inicia un nuevo proceso. Hay * miles * de operaciones de archivos y registro en curso. –