From: Franck Bui Date: Mon, 6 May 2019 13:49:23 +0000 (+0200) Subject: udevd: change the default value of udev.children-max (again) X-Git-Tag: v243-rc1~420 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=88bd5a32e89125d79d68bf846d1af419ebb8cb4f;p=thirdparty%2Fsystemd.git udevd: change the default value of udev.children-max (again) Follow-up for faae64fa3dc22738b3af669579a33055b9d71432, which increased the default number of udev workers per cpu regardless of how big the system is. It's not really clear from the commit message if the new number of workers improved the overall time for the boot process or only reduced the number of times the max number of children limit was reached (and in this case 5406c36844b3 commit might have been more appropriate in the first place). But systems with ~1000 CPUs are not rare these days and the worker numbers get quite large with CPU factor of 8. Spawning more than 2000 workers can't be healthy on any system, no matter how big. Indeed the main mistake is the belief that udev is CPU-intensive, and thus the number of allowed workers has to increase with the number of CPUs. It is not, at probably has never been. It's I/O bound, and sometimes, bound by resources such as locks. This is an argument to: - scale only weakly with the number of CPUs, and the rationale to switch back to a scale factor C=2 but with a higher offset number which should affect systems with a small number of CPUs only. With this patch applied the offset is increased from O=8 to O=16. - put an absolute maximum limit to make sure no more than 2048 workers are spawned no matter how big the system is. This still provides more workers for the laptop cases (where the number of CPUs is limited), while avoiding sky-rocketing numbers for big systems. Note that on most desktop systems, the memory limit will kick in. The following table collects numbers about children-max. For each scenario, the first column is the "cpu_limit" limit, and the second number is the minimum amount of memory for the "cpu_limit" limit to become relevant (with less RAM, memory will limit the number of children thus "mem_limit" will become the active limit). | > v240 | < v240 | this patch | CPUs | C = 8, O = 8 | C = 2, O = 8 | C = 2, O = 16 | ------------------------------------------------------- 1 | 16 2 | 10 1.3 | 18 2 | 2 | 24 3 | 12 1.5 | 20 2 | 4 | 40 5 | 16 2 | 24 3 | 8 | 72 9 | 24 3 | 32 4 | 16 | 136 17 | 40 5 | 48 5 | 64 | 520 65 | 136 17 | 144 18 | 1024 | 8200 1025 | 2056 263 | 2048 256 | 2048 |16392 2049 | 4104 513 | 2048 256 | This patch is mainly based on Martin Wilck's analyze and comments. --- diff --git a/src/udev/udevd.c b/src/udev/udevd.c index a6f7ee82bbf..873d03bc5e5 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -69,6 +69,8 @@ #include "udev.h" #include "user-util.h" +#define WORKER_NUM_MAX 2048U + static bool arg_debug = false; static int arg_daemonize = false; static ResolveNameTiming arg_resolve_name_timing = RESOLVE_NAME_EARLY; @@ -1745,16 +1747,18 @@ static int run(int argc, char *argv[]) { return r; if (arg_children_max == 0) { + unsigned long cpu_limit, mem_limit; + unsigned long cpu_count = 1; cpu_set_t cpu_set; - unsigned long mem_limit; - - arg_children_max = 8; if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) == 0) - arg_children_max += CPU_COUNT(&cpu_set) * 8; + cpu_count = CPU_COUNT(&cpu_set); + + cpu_limit = cpu_count * 2 + 16; + mem_limit = MAX(physical_memory() / (128UL*1024*1024), 10U); - mem_limit = physical_memory() / (128LU*1024*1024); - arg_children_max = MAX(10U, MIN(arg_children_max, mem_limit)); + arg_children_max = MIN(cpu_limit, mem_limit); + arg_children_max = MIN(WORKER_NUM_MAX, arg_children_max); log_debug("Set children_max to %u", arg_children_max); }