Commit 60035a39 authored by Sebastian Andrzej Siewior's avatar Sebastian Andrzej Siewior Committed by Peter Zijlstra
Browse files

tools/perf: Allow to select the number of hash buckets



Add the -b/ --buckets argument to specify the number of hash buckets for
the private futex hash. This is directly passed to
    prctl(PR_FUTEX_HASH, PR_FUTEX_HASH_SET_SLOTS, buckets, immutable)

and must return without an error if specified. The `immutable' is 0 by
default and can be set to 1 via the -I/ --immutable argument.
The size of the private hash is verified with PR_FUTEX_HASH_GET_SLOTS.
If PR_FUTEX_HASH_GET_SLOTS failed then it is assumed that an older
kernel was used without the support and that the global hash is used.

Signed-off-by: default avatarSebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20250416162921.513656-20-bigeasy@linutronix.de
parent f25051dc
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,6 +3,7 @@ perf-bench-y += sched-pipe.o
perf-bench-y += sched-seccomp-notify.o
perf-bench-y += syscall.o
perf-bench-y += mem-functions.o
perf-bench-y += futex.o
perf-bench-y += futex-hash.o
perf-bench-y += futex-wake.o
perf-bench-y += futex-wake-parallel.o
+7 −0
Original line number Diff line number Diff line
@@ -18,9 +18,11 @@
#include <stdlib.h>
#include <linux/compiler.h>
#include <linux/kernel.h>
#include <linux/prctl.h>
#include <linux/zalloc.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <perf/cpumap.h>

#include "../util/mutex.h"
@@ -50,9 +52,12 @@ struct worker {
static struct bench_futex_parameters params = {
	.nfutexes = 1024,
	.runtime  = 10,
	.nbuckets = -1,
};

static const struct option options[] = {
	OPT_INTEGER( 'b', "buckets", &params.nbuckets, "Specify amount of hash buckets"),
	OPT_BOOLEAN( 'I', "immutable", &params.buckets_immutable, "Make the hash buckets immutable"),
	OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
	OPT_UINTEGER('r', "runtime", &params.runtime, "Specify runtime (in seconds)"),
	OPT_UINTEGER('f', "futexes", &params.nfutexes, "Specify amount of futexes per threads"),
@@ -118,6 +123,7 @@ static void print_summary(void)
	printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
	       !params.silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
	       (int)bench__runtime.tv_sec);
	futex_print_nbuckets(&params);
}

int bench_futex_hash(int argc, const char **argv)
@@ -161,6 +167,7 @@ int bench_futex_hash(int argc, const char **argv)

	if (!params.fshared)
		futex_flag = FUTEX_PRIVATE_FLAG;
	futex_set_nbuckets_param(&params);

	printf("Run summary [PID %d]: %d threads, each operating on %d [%s] futexes for %d secs.\n\n",
	       getpid(), params.nthreads, params.nfutexes, params.fshared ? "shared":"private", params.runtime);
+5 −0
Original line number Diff line number Diff line
@@ -41,10 +41,13 @@ static struct stats throughput_stats;
static struct cond thread_parent, thread_worker;

static struct bench_futex_parameters params = {
	.nbuckets = -1,
	.runtime  = 10,
};

static const struct option options[] = {
	OPT_INTEGER( 'b', "buckets", &params.nbuckets, "Specify amount of hash buckets"),
	OPT_BOOLEAN( 'I', "immutable", &params.buckets_immutable, "Make the hash buckets immutable"),
	OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
	OPT_UINTEGER('r', "runtime", &params.runtime, "Specify runtime (in seconds)"),
	OPT_BOOLEAN( 'M', "multi",   &params.multi, "Use multiple futexes"),
@@ -67,6 +70,7 @@ static void print_summary(void)
	printf("%sAveraged %ld operations/sec (+- %.2f%%), total secs = %d\n",
	       !params.silent ? "\n" : "", avg, rel_stddev_stats(stddev, avg),
	       (int)bench__runtime.tv_sec);
	futex_print_nbuckets(&params);
}

static void toggle_done(int sig __maybe_unused,
@@ -203,6 +207,7 @@ int bench_futex_lock_pi(int argc, const char **argv)
	mutex_init(&thread_lock);
	cond_init(&thread_parent);
	cond_init(&thread_worker);
	futex_set_nbuckets_param(&params);

	threads_starting = params.nthreads;
	gettimeofday(&bench__start, NULL);
+6 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ static unsigned int threads_starting;
static int futex_flag = 0;

static struct bench_futex_parameters params = {
	.nbuckets = -1,
	/*
	 * How many tasks to requeue at a time.
	 * Default to 1 in order to make the kernel work more.
@@ -50,6 +51,8 @@ static struct bench_futex_parameters params = {
};

static const struct option options[] = {
	OPT_INTEGER( 'b', "buckets", &params.nbuckets, "Specify amount of hash buckets"),
	OPT_BOOLEAN( 'I', "immutable", &params.buckets_immutable, "Make the hash buckets immutable"),
	OPT_UINTEGER('t', "threads",  &params.nthreads, "Specify amount of threads"),
	OPT_UINTEGER('q', "nrequeue", &params.nrequeue, "Specify amount of threads to requeue at once"),
	OPT_BOOLEAN( 's', "silent",   &params.silent, "Silent mode: do not display data/details"),
@@ -77,6 +80,7 @@ static void print_summary(void)
	       params.nthreads,
	       requeuetime_avg / USEC_PER_MSEC,
	       rel_stddev_stats(requeuetime_stddev, requeuetime_avg));
	futex_print_nbuckets(&params);
}

static void *workerfn(void *arg __maybe_unused)
@@ -204,6 +208,8 @@ int bench_futex_requeue(int argc, const char **argv)
	if (params.broadcast)
		params.nrequeue = params.nthreads;

	futex_set_nbuckets_param(&params);

	printf("Run summary [PID %d]: Requeuing %d threads (from [%s] %p to %s%p), "
	       "%d at a time.\n\n",  getpid(), params.nthreads,
	       params.fshared ? "shared":"private", &futex1,
+8 −1
Original line number Diff line number Diff line
@@ -57,9 +57,13 @@ static struct stats waketime_stats, wakeup_stats;
static unsigned int threads_starting;
static int futex_flag = 0;

static struct bench_futex_parameters params;
static struct bench_futex_parameters params = {
	.nbuckets = -1,
};

static const struct option options[] = {
	OPT_INTEGER( 'b', "buckets", &params.nbuckets, "Specify amount of hash buckets"),
	OPT_BOOLEAN( 'I', "immutable", &params.buckets_immutable, "Make the hash buckets immutable"),
	OPT_UINTEGER('t', "threads", &params.nthreads, "Specify amount of threads"),
	OPT_UINTEGER('w', "nwakers", &params.nwakes, "Specify amount of waking threads"),
	OPT_BOOLEAN( 's', "silent",  &params.silent, "Silent mode: do not display data/details"),
@@ -218,6 +222,7 @@ static void print_summary(void)
	       params.nthreads,
	       waketime_avg / USEC_PER_MSEC,
	       rel_stddev_stats(waketime_stddev, waketime_avg));
	futex_print_nbuckets(&params);
}


@@ -291,6 +296,8 @@ int bench_futex_wake_parallel(int argc, const char **argv)
	if (!params.fshared)
		futex_flag = FUTEX_PRIVATE_FLAG;

	futex_set_nbuckets_param(&params);

	printf("Run summary [PID %d]: blocking on %d threads (at [%s] "
	       "futex %p), %d threads waking up %d at a time.\n\n",
	       getpid(), params.nthreads, params.fshared ? "shared":"private",
Loading