ctdb-locking: Use vfork instead of fork to exec helpers
authorAmitay Isaacs <amitay@gmail.com>
Tue, 19 Nov 2013 04:31:39 +0000 (15:31 +1100)
committerMichael Adam <obnox@samba.org>
Wed, 27 Nov 2013 17:46:16 +0000 (18:46 +0100)
There is a significant overhead using fork() over vfork(), specially
when the child process execs a helper.  The overhead is in memory space
and time.

    # strace -c ./test_fork 1024 200
    count=1024, size=204800, total=200M
    failed fork=0
    time for fork() = 4879.597000 us
    % time     seconds  usecs/call     calls    errors syscall
    ------ ----------- ----------- --------- --------- ----------------
    100.00    4.543321        3304      1375       375 clone
      0.00    0.000071           0      1033           mmap
      0.00    0.000000           0         1           read
      0.00    0.000000           0         3           write
      0.00    0.000000           0         2           open
      0.00    0.000000           0         2           close
      0.00    0.000000           0         3           fstat
      0.00    0.000000           0         3           mprotect
      0.00    0.000000           0         1           munmap
      0.00    0.000000           0         3           brk
      0.00    0.000000           0         1         1 access
      0.00    0.000000           0         1           execve
      0.00    0.000000           0         1           arch_prctl
    ------ ----------- ----------- --------- --------- ----------------
    100.00    4.543392                  2429       376 total

    # strace -c ./test_vfork 1024 200
    count=1024, size=204800, total=200M
    failed fork=0
    time for fork() = 82.041000 us
    % time     seconds  usecs/call     calls    errors syscall
    ------ ----------- ----------- --------- --------- ----------------
     96.47    0.001204           1      1000           vfork
      3.53    0.000044           0      1033           mmap
      0.00    0.000000           0         1           read
      0.00    0.000000           0         3           write
      0.00    0.000000           0         2           open
      0.00    0.000000           0         2           close
      0.00    0.000000           0         3           fstat
      0.00    0.000000           0         3           mprotect
      0.00    0.000000           0         1           munmap
      0.00    0.000000           0         3           brk
      0.00    0.000000           0         1         1 access
      0.00    0.000000           0         1           execve
      0.00    0.000000           0         1           arch_prctl
    ------ ----------- ----------- --------- --------- ----------------
    100.00    0.001248                  2054         1 total

Signed-off-by: Amitay Isaacs <amitay@gmail.com>
Reviewed-by: Michael Adam <obnox@samba.org>
ctdb/server/ctdb_lock.c

index 4f9e19bd28e65875e73d00b1cd635701cb68e075..b71fac28f1959797a027f650aa25e7774577cab2 100644 (file)
@@ -528,10 +528,12 @@ static void ctdb_lock_timeout_handler(struct tevent_context *ev,
                }
        }
        if (debug_locks != NULL) {
-               pid = fork();
+               pid = vfork();
                if (pid == 0) {
                        execl(debug_locks, debug_locks, NULL);
+                       _exit(0);
                }
+               ctdb_track_child(ctdb, pid);
        } else {
                DEBUG(DEBUG_WARNING,
                      (__location__
@@ -810,7 +812,7 @@ static void ctdb_lock_schedule(struct ctdb_context *ctdb)
                return;
        }
 
-       lock_ctx->child = ctdb_fork(ctdb);
+       lock_ctx->child = vfork();
 
        if (lock_ctx->child == (pid_t)-1) {
                DEBUG(DEBUG_ERR, ("Failed to create a child in ctdb_lock_schedule\n"));
@@ -832,6 +834,7 @@ static void ctdb_lock_schedule(struct ctdb_context *ctdb)
        }
 
        /* Parent process */
+       ctdb_track_child(ctdb, lock_ctx->child);
        close(lock_ctx->fd[1]);
 
        talloc_set_destructor(lock_ctx, ctdb_lock_context_destructor);