From: Kay Sievers Date: Thu, 10 Aug 2006 10:50:53 +0000 (+0200) Subject: udevd: autotune max_childs/max_childs_running X-Git-Tag: 174~2209 X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=f051e340699286831b90b242d843eb1a38c2b19f udevd: autotune max_childs/max_childs_running --- diff --git a/udevcontrol.c b/udevcontrol.c index 3044d02f0..9231f2e08 100644 --- a/udevcontrol.c +++ b/udevcontrol.c @@ -53,12 +53,13 @@ void log_message (int priority, const char *format, ...) static void usage(void) { printf("Usage: udevcontrol COMMAND\n" - " log_priority= set the udev log level for the daemon\n" - " stop_exec_queue keep udevd from executing events, queue only\n" - " start_exec_queue execute events, flush queue\n" - " reload_rules reloads the rules files\n" - " max_childs= maximum number of childs running at the same time\n" - " --help print this help text\n\n"); + " log_priority= set the udev log level for the daemon\n" + " stop_exec_queue keep udevd from executing events, queue only\n" + " start_exec_queue execute events, flush queue\n" + " reload_rules reloads the rules files\n" + " max_childs= maximum number of childs\n" + " max_childs_running= maximum number of childs running at the same time\n" + " --help print this help text\n\n"); } int main(int argc, char *argv[], char *envp[]) @@ -104,11 +105,33 @@ int main(int argc, char *argv[], char *envp[]) *intval = log_priority(val); info("send log_priority=%i", *intval); } else if (!strncmp(arg, "max_childs=", strlen("max_childs="))) { + char *endp; + int count; + intval = (int *) ctrl_msg.buf; val = &arg[strlen("max_childs=")]; ctrl_msg.type = UDEVD_CTRL_SET_MAX_CHILDS; - *intval = atoi(val); + count = strtoul(val, &endp, 0); + if (endp[0] != '\0' || count < 1) { + fprintf(stderr, "invalid number\n"); + goto exit; + } + *intval = count; info("send max_childs=%i", *intval); + } else if (!strncmp(arg, "max_childs_running=", strlen("max_childs_running="))) { + char *endp; + int count; + + intval = (int *) ctrl_msg.buf; + val = &arg[strlen("max_childs_running=")]; + ctrl_msg.type = UDEVD_CTRL_SET_MAX_CHILDS_RUNNING; + count = strtoul(val, &endp, 0); + if (endp[0] != '\0' || count < 1) { + fprintf(stderr, "invalid number\n"); + goto exit; + } + *intval = count; + info("send max_childs_running=%i", *intval); } else if (strcmp(arg, "help") == 0 || strcmp(arg, "--help") == 0 || strcmp(arg, "-h") == 0) { usage(); goto exit; diff --git a/udevd.c b/udevd.c index 45e9aae77..af9e118c5 100644 --- a/udevd.c +++ b/udevd.c @@ -310,7 +310,68 @@ static void msg_queue_insert(struct udevd_uevent_msg *msg) run_exec_q = 1; } -/* runs event and removes event from run queue when finished */ +static int mem_size_mb(void) +{ + int f; + char buf[8192]; + long int len; + const char *pos; + long int memsize; + + f = open("/proc/meminfo", O_RDONLY); + if (f == -1) + return -1; + + len = read(f, buf, sizeof(buf)-1); + close(f); + + if (len <= 0) + return -1; + buf[len] = '\0'; + + pos = strstr(buf, "MemTotal: "); + if (pos == NULL) + return -1; + + if (sscanf(pos, "MemTotal: %ld kB", &memsize) != 1) + return -1; + + return memsize / 1024; +} + +static int cpu_count(void) +{ + int f; + char buf[32768]; + int len; + const char *pos; + int count = 0; + + f = open("/proc/stat", O_RDONLY); + if (f == -1) + return -1; + + len = read(f, buf, sizeof(buf)-1); + close(f); + if (len <= 0) + return -1; + buf[len] = '\0'; + + pos = strstr(buf, "cpu"); + if (pos == NULL) + return -1; + + while (pos != NULL) { + if (strncmp(pos, "cpu", 3) == 0 &&isdigit(pos[3])) + count++; + pos = strstr(&pos[3], "cpu"); + } + + if (count == 0) + return -1; + return count; +} + static int running_processes(void) { int f; @@ -325,11 +386,9 @@ static int running_processes(void) len = read(f, buf, sizeof(buf)-1); close(f); - if (len <= 0) return -1; - else - buf[len] = '\0'; + buf[len] = '\0'; pos = strstr(buf, "procs_running "); if (pos == NULL) @@ -625,12 +684,17 @@ static void get_ctrl_msg(void) info("udevd message (UDEVD_SET_MAX_CHILDS) received, max_childs=%i", *intval); max_childs = *intval; break; + case UDEVD_CTRL_SET_MAX_CHILDS_RUNNING: + intval = (int *) ctrl_msg.buf; + info("udevd message (UDEVD_SET_MAX_CHILDS_RUNNING) received, max_childs=%i", *intval); + max_childs_running = *intval; + break; case UDEVD_CTRL_RELOAD_RULES: info("udevd message (RELOAD_RULES) received"); reload_config = 1; break; default: - dbg("unknown message type"); + err("unknown control message type"); } } @@ -998,16 +1062,26 @@ int main(int argc, char *argv[], char *envp[]) value = getenv("UDEVD_MAX_CHILDS"); if (value) max_childs = strtoul(value, NULL, 10); - else - max_childs = UDEVD_MAX_CHILDS; + else { + int memsize = mem_size_mb(); + if (memsize > 0) + max_childs = 128 + (memsize / 4); + else + max_childs = UDEVD_MAX_CHILDS; + } info("initialize max_childs to %u", max_childs); /* start to throttle forking if maximum number of _running_ childs is reached */ value = getenv("UDEVD_MAX_CHILDS_RUNNING"); if (value) max_childs_running = strtoull(value, NULL, 10); - else - max_childs_running = UDEVD_MAX_CHILDS_RUNNING; + else { + int cpus = cpu_count(); + if (cpus > 0) + max_childs_running = 8 + (8 * cpus); + else + max_childs_running = UDEVD_MAX_CHILDS_RUNNING; + } info("initialize max_childs_running to %u", max_childs_running); /* clear environment for forked event processes */ diff --git a/udevd.h b/udevd.h index b852b5224..688e6d52e 100644 --- a/udevd.h +++ b/udevd.h @@ -46,6 +46,7 @@ enum udevd_ctrl_msg_type { UDEVD_CTRL_START_EXEC_QUEUE, UDEVD_CTRL_SET_LOG_LEVEL, UDEVD_CTRL_SET_MAX_CHILDS, + UDEVD_CTRL_SET_MAX_CHILDS_RUNNING, UDEVD_CTRL_RELOAD_RULES, };