summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Sheplyakov <asheplyakov@altlinux.org>2021-04-27 14:48:53 +0400
committerAlexey Sheplyakov <asheplyakov@altlinux.org>2021-04-27 19:07:00 +0400
commitac121434aae7d16053d005c508073bf1a8108095 (patch)
treebf050de6f61b7ec0aeb90af25da1a84d67461d9f
parentde21b1a43737fbcf47967a706dab4c60521dbbb1 (diff)
downloaddistcc-git-ac121434aae7d16053d005c508073bf1a8108095.tar.gz
prefork: use available cores more efficiently
Observed behavior ----------------- When compiling a big C project (Linux kernel) with distcc compilation nodes never use 100% of CPU time, instead a system is 25 -- 40% idle (despite --jobs is set to 3x the number of cores). Analysis -------- Linux kernel consists of many relatively small C sources and header files. Compiling a single source file typically takes a fraction of a second (although there are quite a number of "heavier" sources). `dcc_preforked_child` exits after 50 requests. Thus a typical lifetime of a worker process is just a few seconds. However `dcc_create_kids` sleeps for a second after every fork. Also `dcc_preforked_child` sleeps for yet another second. Which is >= 25% of a typical child lifetime. As a result distccd is unable to use available CPU time (system load is always <= 75% during the compilation). Fix --- Removed `sleep` from `dcc_preforking_parent` and `dcc_create_kids`. Also made `dcc_preforked_child` process compilation jobs for at least 60 seconds. Result ------ Kernel compilation time (two 6-core nodes) reduced almost 2x: before: 20 minutes, after: 12 minutes Closes: #420
-rw-r--r--src/prefork.c17
1 files changed, 7 insertions, 10 deletions
diff --git a/src/prefork.c b/src/prefork.c
index 38e3a19..d7e1d84 100644
--- a/src/prefork.c
+++ b/src/prefork.c
@@ -37,6 +37,7 @@
#include <syslog.h>
#include <signal.h>
#include <fcntl.h>
+#include <time.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -91,10 +92,6 @@ int dcc_preforking_parent(int listen_fd)
/* wait for any children to exit, and then start some more */
dcc_reap_kids(TRUE);
-
- /* Another little safety brake here: since children should not exit
- * too quickly, pausing before starting them should be harmless. */
- sleep(1);
}
}
}
@@ -133,10 +130,6 @@ static void dcc_create_kids(int listen_fd) {
++dcc_nkids;
rs_trace("up to %d children", dcc_nkids);
}
-
- /* Don't start them too quickly, or we might overwhelm a machine
- * that's having trouble. */
- sleep(1);
}
}
@@ -151,9 +144,12 @@ static void dcc_create_kids(int listen_fd) {
static int dcc_preforked_child(int listen_fd)
{
int ireq;
- const int child_lifetime = 50;
+ time_t start, now;
+ const int child_requests = 50;
+ const time_t child_lifetime = 60 /* seconds */;
+ start = now = time(NULL);
- for (ireq = 0; ireq < child_lifetime; ireq++) {
+ for (ireq = 0; ireq < child_requests || now - start < child_lifetime; ireq++) {
int acc_fd;
struct dcc_sockaddr_storage cli_addr;
socklen_t cli_len;
@@ -188,6 +184,7 @@ static int dcc_preforked_child(int listen_fd)
(struct sockaddr *) &cli_addr, cli_len);
dcc_close(acc_fd);
+ now = time(NULL);
}
rs_log_info("worn out");