2012-05-22 13 views
11

Sigo escuchando que es muy costoso crear un nuevo proceso en Windows. Pero no puedo encontrar los números exactos. ¿Hay un número de parque de ciclos? ¿Cuántos milisegundos en un procesador de doble núcleo a 2 GHz?¿Cuál es la sobrecarga de creación de proceso en Windows?

Escribí un programa de prueba en Python y medí 5 ms por proceso, pero no sé cuánto de esto es una sobrecarga adicional de Python. Supongo que no mucho.

+0

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

+0

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

+0

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. –

Respuesta

18

¡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 ...

+0

¡Buena respuesta!¡Vas a ganar algún tipo de insignia por responder esta pregunta de 2 años! – japreiss

Cuestiones relacionadas