summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitrii Dolgov <9erthalion6@gmail.com>2026-02-08 13:22:24 +0100
committerArnaldo Carvalho de Melo <acme@redhat.com>2026-02-08 19:16:24 -0300
commit2e05bb52a12d3cdb81f3b6f5de5cb3905d383552 (patch)
tree38b851124b1bc6fca2c918aa2446b239a47036d2
parent6a32fa5ccd33da5d187ec6e78f3b45683399ab66 (diff)
perf test workload: Add code_with_type test workload
The purpose of the workload is to gather samples of rust runtime. To achieve that it has a dummy rust library linked with it. Per recommendations for such scenarios [1], the rust library is statically linked. An example: $ perf record perf test -w code_with_type [ perf record: Woken up 1 times to write data ] [ perf record: Captured and wrote 0.160 MB perf.data (4074 samples) ] $ perf report --stdio --dso perf -s srcfile,srcline 45.16% ub_checks.rs ub_checks.rs:72 6.72% code_with_type.rs code_with_type.rs:15 6.64% range.rs range.rs:767 4.26% code_with_type.rs code_with_type.rs:21 4.23% range.rs range.rs:0 3.99% code_with_type.rs code_with_type.rs:16 [...] [1]: https://doc.rust-lang.org/reference/linkage.html#mixed-rust-and-foreign-codebases Signed-off-by: Dmitrii Dolgov <9erthalion6@gmail.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Ian Rogers <irogers@google.com> Cc: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
-rw-r--r--tools/build/Makefile.build14
-rw-r--r--tools/perf/Makefile.perf2
-rw-r--r--tools/perf/tests/builtin-test.c4
-rw-r--r--tools/perf/tests/tests.h4
-rw-r--r--tools/perf/tests/workloads/Build5
-rw-r--r--tools/perf/tests/workloads/code_with_type.c46
-rw-r--r--tools/perf/tests/workloads/code_with_type.rs23
-rw-r--r--tools/scripts/Makefile.include2
8 files changed, 99 insertions, 1 deletions
diff --git a/tools/build/Makefile.build b/tools/build/Makefile.build
index 3584ff308607..60e65870eae1 100644
--- a/tools/build/Makefile.build
+++ b/tools/build/Makefile.build
@@ -76,6 +76,14 @@ quiet_cmd_host_ld_multi = HOSTLD $@
cmd_host_ld_multi = $(if $(strip $(obj-y)),\
$(HOSTLD) -r -o $@ $(filter $(obj-y),$^),rm -f $@; $(HOSTAR) rcs $@)
+rust_common_cmd = \
+ $(RUSTC) $(rust_flags) \
+ --crate-type staticlib -L $(objtree)/rust/ \
+ --emit=dep-info=$(depfile),link
+
+quiet_cmd_rustc_a_rs = $(RUSTC) $(quiet_modtag) $@
+ cmd_rustc_a_rs = $(rust_common_cmd) -o $@ -g $< $(cmd_objtool)
+
ifneq ($(filter $(obj),$(hostprogs)),)
host = host_
endif
@@ -105,6 +113,12 @@ $(OUTPUT)%.s: %.c FORCE
$(call rule_mkdir)
$(call if_changed_dep,cc_s_c)
+# it's recommended to build a static rust library, when a foreight (to rust)
+# linker is used.
+$(OUTPUT)%.a: %.rs FORCE
+ $(call rule_mkdir)
+ $(call if_changed_dep,rustc_a_rs)
+
# bison and flex files are generated in the OUTPUT directory
# so it needs a separate rule to depend on them properly
$(OUTPUT)%-bison.o: $(OUTPUT)%-bison.c FORCE
diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
index 2a7e5814b159..a6d8ca3e9233 100644
--- a/tools/perf/Makefile.perf
+++ b/tools/perf/Makefile.perf
@@ -271,7 +271,7 @@ ifeq ($(PYLINT),1)
PYLINT := $(shell which pylint 2> /dev/null)
endif
-export srctree OUTPUT RM CC CXX LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
+export srctree OUTPUT RM CC CXX RUSTC LD AR CFLAGS CXXFLAGS V BISON FLEX AWK
export HOSTCC HOSTLD HOSTAR HOSTCFLAGS SHELLCHECK MYPY PYLINT
include $(srctree)/tools/build/Makefile.include
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index e2490652f030..06507066213b 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -154,6 +154,10 @@ static struct test_workload *workloads[] = {
&workload__landlock,
&workload__traploop,
&workload__inlineloop,
+
+#ifdef HAVE_RUST_SUPPORT
+ &workload__code_with_type,
+#endif
};
#define workloads__for_each(workload) \
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h
index 1f0f8b267fb1..f5f1238d1f7f 100644
--- a/tools/perf/tests/tests.h
+++ b/tools/perf/tests/tests.h
@@ -242,6 +242,10 @@ DECLARE_WORKLOAD(landlock);
DECLARE_WORKLOAD(traploop);
DECLARE_WORKLOAD(inlineloop);
+#ifdef HAVE_RUST_SUPPORT
+DECLARE_WORKLOAD(code_with_type);
+#endif
+
extern const char *dso_to_test;
extern const char *test_objdump_path;
diff --git a/tools/perf/tests/workloads/Build b/tools/perf/tests/workloads/Build
index 866a00bd14a0..2ef97f7affce 100644
--- a/tools/perf/tests/workloads/Build
+++ b/tools/perf/tests/workloads/Build
@@ -10,6 +10,11 @@ perf-test-y += landlock.o
perf-test-y += traploop.o
perf-test-y += inlineloop.o
+ifeq ($(CONFIG_RUST_SUPPORT),y)
+ perf-test-y += code_with_type.o
+ perf-test-y += code_with_type.a
+endif
+
CFLAGS_sqrtloop.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
CFLAGS_leafloop.o = -g -O0 -fno-inline -fno-omit-frame-pointer -U_FORTIFY_SOURCE
CFLAGS_brstack.o = -g -O0 -fno-inline -U_FORTIFY_SOURCE
diff --git a/tools/perf/tests/workloads/code_with_type.c b/tools/perf/tests/workloads/code_with_type.c
new file mode 100644
index 000000000000..65d7be7dac24
--- /dev/null
+++ b/tools/perf/tests/workloads/code_with_type.c
@@ -0,0 +1,46 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include <linux/compiler.h>
+#include "../tests.h"
+
+extern void test_rs(uint count);
+
+static volatile sig_atomic_t done;
+
+static void sighandler(int sig __maybe_unused)
+{
+ done = 1;
+}
+
+static int code_with_type(int argc, const char **argv)
+{
+ int sec = 1, num_loops = 100;
+
+ pthread_setname_np(pthread_self(), "perf-code-with-type");
+ if (argc > 0)
+ sec = atoi(argv[0]);
+
+ if (argc > 1)
+ num_loops = atoi(argv[1]);
+
+ signal(SIGINT, sighandler);
+ signal(SIGALRM, sighandler);
+ alarm(sec);
+
+ /*
+ * Rust doesn't have signal management in the standard library. To
+ * not deal with any external crates, offload signal handling to the
+ * outside code.
+ */
+ while (!done) {
+ test_rs(num_loops);
+ continue;
+ }
+
+ return 0;
+}
+
+DEFINE_WORKLOAD(code_with_type);
diff --git a/tools/perf/tests/workloads/code_with_type.rs b/tools/perf/tests/workloads/code_with_type.rs
new file mode 100644
index 000000000000..3b91e51919dd
--- /dev/null
+++ b/tools/perf/tests/workloads/code_with_type.rs
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// We're going to look for this structure in the data type profiling report
+#[allow(dead_code)]
+struct Buf {
+ data1: u64,
+ data2: String,
+ data3: u64,
+}
+
+#[no_mangle]
+pub extern "C" fn test_rs(count: u32) {
+ let mut b = Buf { data1: 0, data2: String::from("data"), data3: 0};
+
+ for _ in 1..count {
+ b.data1 += 1;
+ if b.data1 == 123 {
+ b.data1 += 1;
+ }
+
+ b.data3 += b.data1;
+ }
+}
diff --git a/tools/scripts/Makefile.include b/tools/scripts/Makefile.include
index ded48263dd5e..b5ecf137febc 100644
--- a/tools/scripts/Makefile.include
+++ b/tools/scripts/Makefile.include
@@ -94,6 +94,8 @@ LLVM_STRIP ?= llvm-strip
# Some tools require bpftool
SYSTEM_BPFTOOL ?= bpftool
+RUSTC ?= rustc
+
ifeq ($(CC_NO_CLANG), 1)
EXTRA_WARNINGS += -Wstrict-aliasing=3