Chiharu の日記

絵描き C/C++ プログラマーの日記です。

Cygwin の fork() は遅い?

Cygwin で fork() の時間を調べてみました。Core i7 + SSD の実測で 1 呼び出しあたり 2ms くらいでした。vfork() でなく fork() でも似たり寄ったりです。/bin の各ツールが Windows におけるスレッド起動のノリで fork() を使うことを考慮すると、遅い、のかな。

#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <pthread.h>
#include <windows.h>

/* vfork() */
pid_t test_vfork()
{
 pid_t pid;
 
 pid = vfork();
 if (pid == 0) {
  exit(0);
 }
 
 return pid;
}

/* vfork() & execvp() */
pid_t test_vfork_execvp()
{
 pid_t pid;
 
 char* argv[] = {
  "rm",
  "xxx",
  NULL,
 };
 
 pid = vfork();
 if (pid == 0) {
  execvp(argv[0], argv);
 }
 
 return pid;
}

/* CreateProcess */
void test_create_process(PROCESS_INFORMATION* pi)
{
 STARTUPINFO si;
 
 char cmd[256];
 
 ZeroMemory(&si,sizeof(si));
 si.cb=sizeof(si);
 
 strcpy(cmd, "c:\\cygwin64\\bin\\rm.exe xxx");
 CreateProcess(NULL, cmd, NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL, &si, pi);
}

void wait_process(PROCESS_INFORMATION* pi)
{
 WaitForSingleObject(pi->hProcess, INFINITE);
 
 CloseHandle(pi->hThread);
 CloseHandle(pi->hProcess);
}

/* pthread_create & CreateProcess */
void* thread_proc(void* arg)
{
 return arg;
}

pthread_t test_pthread_create()
{
 pthread_t th;
 
 pthread_create(&th, NULL, thread_proc, NULL);
 
 return th;
}

void test_pthread_wait(pthread_t th)
{
 pthread_join(th, NULL);
}

double gettimeofday_sec()
{
 struct timeval tv;
 gettimeofday(&tv, NULL);
 return tv.tv_sec + tv.tv_usec * 1e-6;
}

/* 計測 */
#define COUNT 1000
pid_t pid[COUNT];
PROCESS_INFORMATION pinfo[COUNT];
pthread_t ths[COUNT];

int main()
{
 double tp, tc;
 size_t i;
 int status;
 
 /* vfork() */
 tp = gettimeofday_sec();
 
 for (i = 0; i < COUNT; i++) {
  pid[i] = test_vfork();
 }
 for (i = 0; i < COUNT; i++) {
  waitpid(pid[i], &status, WUNTRACED);
 }
 
 tc = gettimeofday_sec() - tp;
 
 printf("vfork() : %.3f ms/call\n", (double) tc / COUNT * 1000);
 
 /* vfork() & execvp() */
 tp = gettimeofday_sec();
 
 for (i = 0; i < COUNT; i++) {
  pid[i] = test_vfork_execvp();
 }
 for (i = 0; i < COUNT; i++) {
  waitpid(pid[i], &status, WUNTRACED);
 }
 
 tc = gettimeofday_sec() - tp;
 
 printf("vfork() & execvp() : %.3f ms/call\n", (double) tc / COUNT * 1000);
 
 /* CreateProcess() */
 tp = gettimeofday_sec();
 
 for (i = 0; i < COUNT; i++) {
  test_create_process(&pinfo[i]);
 }
 for (i = 0; i < COUNT; i++) {
  wait_process(&pinfo[i]);
 }
 
 tc = gettimeofday_sec() - tp;
 
 printf("CreateProcess() : %.3f ms/call\n", (double) tc / COUNT * 1000);
 
 /* pthread_create() */
 tp = gettimeofday_sec();
 
 for (i = 0; i < COUNT; i++) {
  ths[i] = test_pthread_create();
 }
 for (i = 0; i < COUNT; i++) {
  test_pthread_wait(ths[i]);
 }
 
 tc = gettimeofday_sec() - tp;
 
 printf("pthread_create() : %.3f ms/call\n", (double) tc / COUNT * 1000);
 
 return 0;
}