How to calculate run time for fork() system call in C?
Asked Answered
M

1

6

I'm trying to find the run time of the fork() system call. Each child process needs to immediately exit, and the parent needs to wait() on each child before creating the next. I also want to use the shell built-in command named time to measure the execution time of a program.

I have this code so far, but not sure If I'm doing it right.

#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>

int global = 100;

int main(int argc, char** argv)
{
    int local = 5;

    pid_t pid;

    pid = fork();
    if (pid < 0) {
        fprintf(stderr, "error -- failed to fork()");
        return 1;
    }

    if (pid > 0) {

        int child_ret;

        waitpid(pid, &child_ret, 0);
        printf("parent -- global: %i, local: %i\n", global, local);
        printf("parent -- child exited with code %i\n", child_ret);
    } else {
        global++;
        local++;

        printf("child -- global: %i, local: %i\n", global, local);
        exit (0);
    }
}
Maltz answered 21/1, 2016 at 6:46 Comment(4)
Take a look at the getrusage system call.Intercontinental
Does the code work? If yes, you should post on codereview.stackexchange.com. If the code does not work, please say exactly why you think so: what error or unexpected behavior are you observing?Metaplasm
You're problably confused because the local and global don't change for your parent-process, but yes, your code looks correct.Mezereon
You should not call exit in the child. You should call _exit. If you call exit in the child, it will run all the parent's "at exit" handlers, and the results of running an at exit handler twice can be unpredictable. This has caused serious bugs with security consequences in the past, so don't get into the habit of mismanaging processes.Essene
E
2

Read first time(7) and consider using clock_gettime(2) & getrusage(2); you could use clock_gettime around the fork (in the parent process) if you wanted only to measure the time for that fork(2) syscall itself (it is very small - perhaps a millisecond -, and not really significant).

Use errno (e.g. print strerror(errno) or use perror) in failure cases.

Notice that fork timing might slightly depends upon the size of your virtual address space and resident set size. You might also use strace timing abilities; in practice fork is quick enough (often, less than one millisecond, and sometimes a few dozens of microseconds; because it is using lazy copy-on-write techniques)

So the fork is quick, the child execve could take a few more microseconds, the program startup time in the child is also significant (ld-linux(8) is performing some relocation before your main of the exec-ed program starts...). What exactly do you want to measure?

In general, the child process quickly calls execve(2) which also takes some time (and of course the executed program may take some arbitrarily long time to finish, and might even "never" finish if it is server like). Perhaps what could matter is the time between just before the fork and the first meaningful instruction in the main of the execve-d program in the child process...

In fact, you can start many processes; a rule of thumb is to fork at most a few hundred times per second, and only if the child is quickly execve-ing some quick program (like /bin/ls of a few dozen files, or date). However, you don't want to have more than a dozen or two of runnable processes at once (on a laptop or desktop), and perhaps even less than 5 runnable processes...

Entopic answered 21/1, 2016 at 6:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.