Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the process creation overhead in Windows?

Tags:

I keep hearing that it's very expensive to create a new process in Windows. But I can't find exact numbers. Is there a ballpark number of cycles? How many milliseconds on a 2GHz dual-core processor?

I wrote a test program in Python and measured 5ms per process, but I don't know how much of that is extra overhead from Python. I'm guessing not much.

like image 221
japreiss Avatar asked May 22 '12 22:05

japreiss


1 Answers

Interresting question!

As said before the overhead is high. Out of curiosity if've quickly written a little benchmark to get a number of thumb how long the creation of a thread and a process takes and how these times are related.

#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); } 

I've made several runs on my computer (i5 3.2GHz; Windows 7) and the values are pretty consistent if the anti virus application is turned off and the benchmark is started from outside of 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 

As expected the variation of CreateProcess(..) is bigger since more system calls are involved and the likelyhood of being interrupted by another thread is higher. Remember that the time to create the thread is even shorter since the time measurement includes the whole control-loop (otherwise GetTickCount(..) would be too inaccurate to measure the time).

Another test on a virtual PC running Windows XP (running on the same machine as mentioned above) produced the following values:

--- 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 the ratio of the average execution times of CreateProcess(..) and CreateThread(..) are pretty close.

It would be interresting to see values of other machines and versions of Windows. I would not be surprised if a ratio of about 300 is about the same on different machines and versions of Windows.

So let's conclude: CreateProcess(..) is much slower than CreateThread(..) on Windows. But actually I'm quite shocked how much slower it really is...

like image 82
Lukas Thomsen Avatar answered Oct 30 '22 03:10

Lukas Thomsen