From 4ea721b2c16597432dcf517170f7859c713d063e Mon Sep 17 00:00:00 2001 From: Amitay Isaacs Date: Tue, 19 Nov 2013 15:31:39 +1100 Subject: [PATCH] ctdb-locking: Use vfork instead of fork to exec helpers 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 Reviewed-by: Michael Adam --- ctdb/server/ctdb_lock.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/ctdb/server/ctdb_lock.c b/ctdb/server/ctdb_lock.c index 4f9e19bd28e..b71fac28f19 100644 --- a/ctdb/server/ctdb_lock.c +++ b/ctdb/server/ctdb_lock.c @@ -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);