Home > Mobile >  fork seems to copy when unnecessary
fork seems to copy when unnecessary

Time:11-17

I'm trying the CoW of fork (see edit for more detailed background, which may be quite unrelated)

#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define N 262144
struct {
    int n;
    int padding[1023];
} arr[N];
int main() {
    int i, sp = 0, t, tx = clock();
    for (i=0; i<N;   i) arr[i].n = i;
    printf ("Init Time: %d\n", clock()-tx);
    #if 1
        sp = fork();
        if(!sp) _exit(0);
        waitpid(sp, &sp, 0);
    #endif
    // 5045 without fork
    // 104192 with fork
    t = clock();
    for (i=0; i<N;   i) arr[i].n = -i;
    printf ("Runner %d Time: %d\n", sp, clock() - t);
    getchar();
    return 0;
}

The fork makes later memory accesses slower.

Do fork copy making it slow? If so, why? I run on Ubuntu 20.04.3 LTS

CodePudding user response:

Try running it under /usr/bin/time -v and watch the Minor (reclaiming a frame) page faults: line.

The fork makes it double even if the child exits immediately.

The increased time seems to be solely due to these page faults.

Presumably, upon a fork, the kernel sets the pages to fault on a write in expectation of a need to copy. If the child is already dead, the need to copy is canceled (the page is no longer shared with anyone so no need to bother copying it), but you still pay for the page faults hitting.

Now if you keep the child alive, then the pagefault handler should also need to do the copy, and indeed, keeping the child alive increases the loop duration several extra times. That should be the full copy-on-write.

#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <time.h>
#include <unistd.h>

#define N 262144
struct {
    int n;
    int padding[1023];
} arr[N];
int main() {
    int i, t, tx = clock();
    pid_t sp=0;
    for (i=0; i<N;   i) arr[i].n = i;
    printf ("Init Time: %ld\n", clock()-tx);

    #if 1
    if(0>(sp = fork())) return 1;
    enum  { KEEP_THE_KID_EH = 1 };
    if(!sp){ if(KEEP_THE_KID_EH){ for(;;) pause(); }  exit(0); }
    #endif

    t = clock();
    for (i=0; i<N;   i) arr[i].n = -i;
    printf ("Runner %ld Time: %ld\n", (long)sp, clock() - t);
    /*getchar();*/
    if(sp) kill(sp,SIGTERM);
    return 0;
}

My times are:

7371 without fork
189073 with fork
1092145 with fork and the kid kept
  • Related