When each object's command line is expanded, kbuild has to figure out on
multiple occasions whether it's built-in or part of a module and which
composite object it belongs to.
This causes the time spent on each directory in the kernel tree to grow
O(n^2) with its object count, which is especially problematic for instance
in drivers/gpu/drm/amd/amdgpu with 310 objects.
No-op builds (i.e. make -j $(nproc) when nothing has changed) are
particularly impacted by this.
Fix the issue by calculating this data once and looking it up thereafter
instead of recomputing it over and over again.
This has a particularly large impact on allmodconfig builds.
Whole build, 128-thread Threadripper 9980X, best of N runs:
before after delta
-------------------------------
x86 defconfig, no-op make, gcc 1.1s 1.1s -0.02s (-2%)
x86 defconfig, no-op make, clang 1.3s 1.3s -0.01s (-1%)
x86 allmodconfig, no-op make, gcc 15.3s 14.5s -0.83s (-5%)
x86 allmodconfig, no-op make, clang 16.2s 15.5s -0.65s (-4%)
x86 allmodconfig, touch mm/vma.c, gcc 35.0s 34.3s -0.77s (-2%)
x86 allmodconfig, touch mm/vma.c, clang 33.7s 33.2s -0.51s (-2%)
Assisted-by: LLM
Reviewed-by: Nicolas Schier <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Signed-off-by: Lorenzo Stoakes (ARM) <[email protected]>
---
scripts/Makefile.build | 8 ++++++++
scripts/Makefile.lib | 7 +++----
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 4349108e75e1..2cabfe85b798 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -122,6 +122,14 @@ multi-obj-m := $(addprefix $(obj)/, $(multi-obj-m))
subdir-ym := $(addprefix $(obj)/, $(subdir-ym))
endif
+# Cache which list each object is in and which composite objects it belongs to,
+# once per object for $(part-of-builtin), $(part-of-module) and
$(modname-multi).
+$(foreach o, $(real-obj-y) $(lib-y), $(eval part-of-builtin_$o := y))
+$(foreach o, $(real-obj-m), $(eval part-of-module_$o := y))
+$(foreach m, $(multi-obj-ym), \
+ $(foreach o, $(call suffix-search, $m, .o, -objs -y -m), \
+ $(eval modname-multi_$o += $(m:.o=))))
+
ifndef obj
$(warning kbuild: Makefile.build is included improperly)
endif
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 0a4fdd8bd975..2f447bc25e7b 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -2,8 +2,7 @@
# Finds the multi-part object the current object will be linked into.
# If the object belongs to two or more multi-part objects, list them all.
-modname-multi = $(sort $(foreach m,$(multi-obj-ym),\
- $(if $(filter $*.o, $(call suffix-search, $m, .o, -objs -y
-m)),$(m:.o=))))
+modname-multi = $(sort $(modname-multi_$*.o))
__modname = $(or $(modname-multi),$(basetarget))
@@ -149,8 +148,8 @@ endif
# If $(is-kernel-object) is 'y', this object will be linked to vmlinux or
modules
is-kernel-object = $(or $(part-of-builtin),$(part-of-module))
-part-of-builtin = $(if $(filter $(basename $@).o, $(real-obj-y) $(lib-y)),y)
-part-of-module = $(if $(filter $(basename $@).o, $(real-obj-m)),y)
+part-of-builtin = $(part-of-builtin_$(basename $@).o)
+part-of-module = $(part-of-module_$(basename $@).o)
quiet_modtag = $(if $(part-of-module),[M], )
modkern_cflags = \
--
2.55.0