24

Windows で新しいプロセスを作成するには非常にコストがかかるとよく耳にします。しかし、正確な数字を見つけることができません。大体のサイクル数はありますか? 2GHz デュアルコア プロセッサで何ミリ秒?

Python でテスト プログラムを作成し、プロセスあたり 5 ミリ秒を測定しましたが、Python からの余分なオーバーヘッドがどれくらいかはわかりません。あまりないと思います。

4

1 に答える 1

32

興味深い質問です!

前に述べたように、オーバーヘッドは高いです。好奇心から、スレッドとプロセスの作成にかかる時間と、これらの時間がどのように関連しているかについて、いくつかの経験を得るために簡単なベンチマークをすばやく作成した場合。

#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 のバージョンでほぼ同じであったとしても、私は驚かないでしょう。

結論として、Windows では CreateProcess(..) は CreateThread(..) よりもはるかに低速です。しかし、実際には、実際にどれだけ遅いかということにかなりショックを受けています...

于 2014-10-22T19:39:00.553 に答える