All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ian Rogers <irogers@google.com>
To: irogers@google.com, acme@kernel.org, namhyung@kernel.org
Cc: adrian.hunter@intel.com, james.clark@linaro.org,
	jolsa@kernel.org,  leo.yan@arm.com, linux-kernel@vger.kernel.org,
	 linux-perf-users@vger.kernel.org, mingo@redhat.com,
	mjeanson@efficios.com,  peterz@infradead.org
Subject: [PATCH v2] perf tests: Improvements to build-test performance
Date: Wed,  2 Sep 2026 21:56:03 -0700	[thread overview]
Message-ID: <20260903045603.3611902-1-irogers@google.com> (raw)
In-Reply-To: <20260902153135.2067365-1-irogers@google.com>

Replace hardcoded 'make' calls with '$(MAKE)' within tests/make to
ensure GNU Make jobserver file descriptors are properly inherited by
nested builds.

Additionally, remove the 'unexport MAKEFLAGS' from
tools/perf/Makefile. This hack was originally added to prevent the
wrapper's internal '-j$(JOBS)' override from crashing when parent
jobserver tokens were present. Instead, use proper GNU Make
conditionals to check for '-j' or 'jobserver' strings within
MAKEFLAGS. If a jobserver is already orchestrating the build,
gracefully back off and let GNU Make manage parallelism natively.

Finally, optimize the 'out' target (which processes 'run_O'
out-of-tree builds) by stripping sequential bottlenecks like $(call
clean) from isolated tmp directories, and wrapping the target list in
a parallel sub-make call.

These combined changes enable 'build-test' out-of-tree targets to
build completely concurrently without severing jobserver tokens.

Unscientifically measured the change lowered the build-test from
around 15 minutes to 10 minutes on a 28 threaded Alderlake CPU. Fixing
the jobserver issues meant the machine remained somewhat usable while
running the test.

Signed-off-by: Ian Rogers <irogers@google.com>
Assisted-by: Antigravity:gemini-3.1-pro
---
v2:
 - Re-structured build-test array in tools/perf/Makefile into explicit
   sequential $(MAKE) passes. This prevents in-tree targets (make_static,
   etc.) from racing to directory corruption when exposed to native
   jobservers.
 - Added '+' prefix to recipe modifiers in tests/make to prevent jobserver
   FDs from being stripped before sub-shell evaluation.
 - Replaced hardcoded -j$(cores) limits in the 'out' sub-make step with
   dynamic jobserver boundary detection to prevent fork-bomb override
   collisions.
 - Restored missing $(call clean) steps via O_CLEAN conditionals to prevent
   in-tree polluted runs from breaking out-of-tree sequences.
 - Removed unconditionally appended $(FEATURES_DUMP_FILE) target restrictions
   from 'out' that threw "No rule to make target" errors on unhandled tests.
 - Fixed 'test_dest_files' to check [ ! -f ] instead of [ ! -x ], removing
   long-standing ghost warnings for non-executable mode-644 targets
   like etc/bash_completion.d/perf.
 - Fixed cosmetic string formatting bugs in GNU Make's print_msg banner
   output.
---
 tools/perf/Makefile   | 35 ++++++++++++++++++++++-------------
 tools/perf/tests/make | 42 ++++++++++++++++++++++++------------------
 2 files changed, 46 insertions(+), 31 deletions(-)

diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 5b713837eede..2cbf4cb5f093 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -14,23 +14,29 @@
 .SUFFIXES:
 
 #
-# We don't want to pass along options like -j:
+# If no parallel build was requested, do a parallel build with multiple jobs,
+# based on the number of CPUs online in this system: 'make -j8' on an 8-CPU
+# system, etc.
 #
-unexport MAKEFLAGS
-
-#
-# Do a parallel build with multiple jobs, based on the number of CPUs online
-# in this system: 'make -j8' on a 8-CPU system, etc.
+# If MAKEFLAGS contains '-j' or 'jobserver', JOBS is intentionally left
+# uninitialized so the native GNU Make jobserver can seamlessly control the
+# parallel bounds of the build.
 #
 # (To override it, run 'make JOBS=1' and similar.)
 #
-ifeq ($(JOBS),)
-  JOBS := $(shell (getconf _NPROCESSORS_ONLN || grep -E -c '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
-  ifeq ($(JOBS),0)
-    JOBS := 1
+ifeq ($(findstring -j,$(MAKEFLAGS)),)
+  ifeq ($(findstring jobserver,$(MAKEFLAGS)),)
+    ifeq ($(JOBS),)
+      JOBS := $(shell (getconf _NPROCESSORS_ONLN || grep -E -c '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
+      ifeq ($(JOBS),0)
+        JOBS := 1
+      endif
+    endif
+    PARALLEL_OPT := -j$(JOBS)
   endif
 endif
 
+
 #
 # Only pass canonical directory names as the output directory:
 #
@@ -58,11 +64,11 @@ else
 endif
 
 define print_msg
-  @printf '  BUILD:   Doing '\''make \033[33m-j'$(JOBS)'\033[m'\'' $(BUILD_TYPE) build\n'
+  @printf '  BUILD:   Doing '\''make\033[33m%s\033[m'\'' $(BUILD_TYPE) build\n' "$(if $(JOBS), -j$(JOBS),)"
 endef
 
 define make
-  @$(MAKE) -f Makefile.perf --no-print-directory -j$(JOBS) O=$(FULL_O) $(SET_DEBUG) $@
+  @$(MAKE) -f Makefile.perf --no-print-directory $(PARALLEL_OPT) O=$(FULL_O) $(SET_DEBUG) $@
 endef
 
 #
@@ -106,7 +112,10 @@ clean:
 # make -C tools/perf -f tests/make
 #
 build-test:
-	@$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory tarpkg make_static make_with_gtk2 out
+	@$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory tarpkg
+	@$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory make_static
+	@$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory make_with_gtk2
+	@$(MAKE) SHUF=1 -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory out
 
 build-test-tarball:
 	@$(MAKE) -f tests/make REUSE_FEATURES_DUMP=1 MK=Makefile SET_PARALLEL=1 --no-print-directory out
diff --git a/tools/perf/tests/make b/tools/perf/tests/make
index d2c2f526e1db..d1d99f5a85ae 100644
--- a/tools/perf/tests/make
+++ b/tools/perf/tests/make
@@ -28,15 +28,17 @@ endif
 
 PARALLEL_OPT=
 ifeq ($(SET_PARALLEL),1)
-  ifeq ($(JOBS),)
-    cores := $(shell (getconf _NPROCESSORS_ONLN || grep -E -c '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
-    ifeq ($(cores),0)
-      cores := 1
+  ifeq ($(findstring jobserver,$(MAKEFLAGS))$(findstring -j,$(MAKEFLAGS)),)
+    ifeq ($(JOBS),)
+      cores := $(shell (getconf _NPROCESSORS_ONLN || grep -E -c '^processor|^CPU[0-9]' /proc/cpuinfo) 2>/dev/null)
+      ifeq ($(cores),0)
+        cores := 1
+      endif
+    else
+      cores=$(JOBS)
     endif
-  else
-    cores=$(JOBS)
+    PARALLEL_OPT="-j$(cores)"
   endif
-  PARALLEL_OPT="-j$(cores)"
 endif
 
 # As per kernel Makefile, avoid funny character set dependencies
@@ -230,7 +232,7 @@ test_make_util_pmu_bison_o := test -f $(PERF_O)/util/pmu-bison.o
 
 define test_dest_files
   for file in $(1); do				\
-    if [ ! -x $$TMP_DEST/$$file ]; then		\
+    if [ ! -f $$TMP_DEST/$$file ]; then		\
       echo "  failed to find: $$file";		\
     fi						\
   done
@@ -310,7 +312,7 @@ clean := @(cd $(PERF); $(MAKE_F) -s $(O_OPT) clean >/dev/null && $(MAKE) -s $(O_
 
 $(run):
 	$(call clean)
-	@TMP_DEST=$$(mktemp -d); \
+	+@TMP_DEST=$$(mktemp -d); \
 	cmd="cd $(PERF) && $(MAKE_F) $($@) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST"; \
 	printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
 	( eval $$cmd ) >> $@ 2>&1; \
@@ -320,7 +322,7 @@ $(run):
 
 make_with_gtk2:
 	$(call clean)
-	@TMP_DEST=$$(mktemp -d); \
+	+@TMP_DEST=$$(mktemp -d); \
 	cmd="cd $(PERF) && $(MAKE_F) $($@) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST"; \
 	printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
 	( eval $$cmd ) >> $@ 2>&1; \
@@ -330,7 +332,7 @@ make_with_gtk2:
 
 make_static:
 	$(call clean)
-	@TMP_DEST=$$(mktemp -d); \
+	+@TMP_DEST=$$(mktemp -d); \
 	cmd="cd $(PERF) && $(MAKE_F) $($@) $(PARALLEL_OPT) $(O_OPT) DESTDIR=$$TMP_DEST"; \
 	printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
 	( eval $$cmd ) >> $@ 2>&1; \
@@ -339,8 +341,10 @@ make_static:
 	rm -rf $@ $$TMP_DEST || (cat $@ ; false)
 
 $(run_O):
+ifneq ($(O_CLEAN),0)
 	$(call clean)
-	@TMP_O=$$(mktemp -d); \
+endif
+	+@TMP_O=$$(mktemp -d); \
 	TMP_DEST=$$(mktemp -d); \
 	cmd="cd $(PERF) && $(MAKE_F) $($(patsubst %_O,%,$@)) $(PARALLEL_OPT) O=$$TMP_O DESTDIR=$$TMP_DEST"; \
 	printf "%*.*s: %s\n" $(max_width) $(max_width) "$@" "$$cmd" && echo $$cmd > $@ && \
@@ -363,18 +367,18 @@ endif
 make_kernelsrc:
 	@echo "- make -C <kernelsrc> $(PARALLEL_OPT) $(K_O_OPT) tools/perf"
 	$(call clean); \
-	(make -C ../.. $(PARALLEL_OPT) $(K_O_OPT) tools/perf) > $@ 2>&1 && \
+	($(MAKE) -C ../.. $(PARALLEL_OPT) $(K_O_OPT) tools/perf) > $@ 2>&1 && \
 	test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false)
 
 make_kernelsrc_tools:
 	@echo "- make -C <kernelsrc>/tools $(PARALLEL_OPT) $(K_O_OPT) perf"
 	$(call clean); \
-	(make -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \
+	($(MAKE) -C ../../tools $(PARALLEL_OPT) $(K_O_OPT) perf) > $@ 2>&1 && \
 	test -x $(KERNEL_O)/tools/perf/perf && rm -f $@ || (cat $@ ; false)
 
 make_libperf:
 	@echo "- make -C lib";
-	make -C lib clean >$@ 2>&1; make -C lib >>$@ 2>&1 && rm $@
+	$(MAKE) -C lib clean >$@ 2>&1; $(MAKE) -C lib >>$@ 2>&1 && rm $@
 
 FEATURES_DUMP_FILE := $(FULL_O)/BUILD_TEST_FEATURE_DUMP
 FEATURES_DUMP_FILE_STATIC := $(FULL_O)/BUILD_TEST_FEATURE_DUMP_STATIC
@@ -383,20 +387,22 @@ all: $(run) $(run_O) tarpkg make_kernelsrc make_kernelsrc_tools
 	@echo OK
 	@rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
 
-out: $(run_O)
+out:
+	$(call clean)
+	@$(MAKE) -f tests/make $(run_O) PARALLEL_OPT= O_CLEAN=0 $(if $(findstring jobserver,$(MAKEFLAGS))$(findstring -j,$(MAKEFLAGS)),,$(if $(cores),-j$(cores)))
 	@echo OK
 	@rm -f $(FEATURES_DUMP_FILE) $(FEATURES_DUMP_FILE_STATIC)
 
 ifeq ($(REUSE_FEATURES_DUMP),1)
 $(FEATURES_DUMP_FILE):
 	$(call clean)
-	@cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) feature-dump"; \
+	@cmd="cd $(PERF) && $(MAKE) FEATURE_DUMP_COPY=$@ $(O_OPT) feature-dump"; \
 	echo "- $@: $$cmd" && echo $$cmd && \
 	( eval $$cmd ) > /dev/null 2>&1
 
 $(FEATURES_DUMP_FILE_STATIC):
 	$(call clean)
-	@cmd="cd $(PERF) && make FEATURE_DUMP_COPY=$@ $(O_OPT) LDFLAGS='-static' feature-dump"; \
+	@cmd="cd $(PERF) && $(MAKE) FEATURE_DUMP_COPY=$@ $(O_OPT) LDFLAGS='-static' feature-dump"; \
 	echo "- $@: $$cmd" && echo $$cmd && \
 	( eval $$cmd ) > /dev/null 2>&1
 
-- 
2.55.0.979.g7e5102b832-goog


  parent reply	other threads:[~2026-09-03  4:56 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-02 15:31 [PATCH v1] perf tests: Improvements to build-test performance Ian Rogers
2026-09-02 15:40 ` sashiko-bot
2026-09-03  4:56 ` Ian Rogers [this message]
2026-09-03  5:04   ` [PATCH v2] " sashiko-bot
2026-09-09 16:10   ` [PATCH v3] " Ian Rogers
2026-09-09 16:21     ` sashiko-bot
2026-09-09 17:38       ` Ian Rogers

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260903045603.3611902-1-irogers@google.com \
    --to=irogers@google.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=james.clark@linaro.org \
    --cc=jolsa@kernel.org \
    --cc=leo.yan@arm.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=mjeanson@efficios.com \
    --cc=namhyung@kernel.org \
    --cc=peterz@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.