Messages in this thread Patch in this message | | | Date | Mon, 20 Jun 2016 13:00:04 -0500 | From | Josh Poimboeuf <> | Subject | [PATCH] perf: add 'perf bench syscall' |
| |
On Wed, Feb 03, 2016 at 11:22:47AM +0100, Ingo Molnar wrote: > > * Andy Lutomirski <luto@amacapital.net> wrote: > > > On Jan 31, 2016 11:42 PM, "Ingo Molnar" <mingo@kernel.org> wrote: > > > > > > > > > * riel@redhat.com <riel@redhat.com> wrote: > > > > > > > (v3: address comments raised by Frederic) > > > > > > > > Running with nohz_full introduces a fair amount of overhead. > > > > Specifically, various things that are usually done from the > > > > timer interrupt are now done at syscall, irq, and guest > > > > entry and exit times. > > > > > > > > However, some of the code that is called every single time > > > > has only ever worked at jiffy resolution. The code in > > > > __acct_update_integrals was also doing some unnecessary > > > > calculations. > > > > > > > > Getting rid of the unnecessary calculations, without > > > > changing any of the functionality in __acct_update_integrals > > > > gets us about an 11% win. > > > > > > > > Not calling the time statistics updating code more than > > > > once per jiffy, like is done on housekeeping CPUs and on > > > > all the CPUs of a non-nohz_full system, shaves off a > > > > further 30%. > > > > > > > > I tested this series with a microbenchmark calling > > > > an invalid syscall number ten million times in a row, > > > > on a nohz_full cpu. > > > > > > > > Run times for the microbenchmark: > > > > > > > > 4.4 3.8 seconds > > > > 4.5-rc1 3.7 seconds > > > > 4.5-rc1 + first patch 3.3 seconds > > > > 4.5-rc1 + first 3 patches 3.1 seconds > > > > 4.5-rc1 + all patches 2.3 seconds > > > > > > Another suggestion (beyond fixing the 32-bit build ;-), could you please stick > > > your syscall microbenchmark into 'perf bench', so that we have a standardized way > > > of checking such numbers? > > > > > > In fact I'd suggest we introduce an entirely new sub-tool for system call > > > performance measurement - and this might be the first functionality of it. > > > > > > I've attached a quick patch that is basically a copy of 'perf bench numa' and > > > which measures getppid() performance (simple syscall where the result is not > > > cached by glibc). > > > > > > I kept the process, threading and memory allocation bits of numa.c, just in case > > > we need them to measure more complex syscalls. Maybe we could keep the threading > > > bits and remove the memory allocation parameters, to simplify the benchmark? > > > > > > Anyway, this could be a good base to start off on. > > > > So much code... > > Arguably 90% of that should be factored out, as it's now a duplicate between > bench/numa.c and bench/syscall.c. > > Technically, for a minimum benchmark, something like this would already be > functional for tools/perf/bench/syscall.c: > > #include "../perf.h" > #include "../util/util.h" > #include "../builtin.h" > #include "bench.h" > > static void run_syscall_benchmark(void) > { > [ .... your benchmark loop as-is ... ] > } > > int bench_syscall(int argc __maybe_unused, const char **argv __maybe_unused, const char *prefix __maybe_unused) > { > run_syscall_benchmark(); > > switch (bench_format) { > case BENCH_FORMAT_DEFAULT: > printf("print results in human-readable format\n"); > break; > case BENCH_FORMAT_SIMPLE: > printf("print results in machine-parseable format\n"); > break; > default: > BUG_ON(1); > } > > return 0; > } > > Plus the small amount of glue for bench_sycall() I sent in the first patch. > > Completely untested. > > If the loop is long enough then even without any timing measurement this would be > usable via: > > perf stat --null --repeat 10 perf bench syscall > > as the 'perf stat' will do the timing and statistics.
How about this:
--------
From: Josh Poimboeuf <jpoimboe@redhat.com> Subject: [PATCH] perf: add 'perf bench syscall'
Add a basic 'perf bench syscall' benchmark which does a getppid() system call in a tight loop.
Suggested-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com> --- tools/perf/bench/Build | 1 + tools/perf/bench/bench.h | 1 + tools/perf/bench/syscall.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++ tools/perf/builtin-bench.c | 18 ++++++++--- 4 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 tools/perf/bench/syscall.c
diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build index 60bf119..0b7395d 100644 --- a/tools/perf/bench/Build +++ b/tools/perf/bench/Build @@ -1,5 +1,6 @@ perf-y += sched-messaging.o perf-y += sched-pipe.o +perf-y += syscall.o perf-y += mem-functions.o perf-y += futex-hash.o perf-y += futex-wake.o diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h index 579a592..bdd6cdc 100644 --- a/tools/perf/bench/bench.h +++ b/tools/perf/bench/bench.h @@ -28,6 +28,7 @@ int bench_numa(int argc, const char **argv, const char *prefix); int bench_sched_messaging(int argc, const char **argv, const char *prefix); int bench_sched_pipe(int argc, const char **argv, const char *prefix); +int bench_syscall_basic(int argc, const char **argv, const char *prefix); int bench_mem_memcpy(int argc, const char **argv, const char *prefix); int bench_mem_memset(int argc, const char **argv, const char *prefix); int bench_futex_hash(int argc, const char **argv, const char *prefix); diff --git a/tools/perf/bench/syscall.c b/tools/perf/bench/syscall.c new file mode 100644 index 0000000..0dc782a --- /dev/null +++ b/tools/perf/bench/syscall.c @@ -0,0 +1,80 @@ +/* + * + * syscall.c + * + * syscall: Benchmark for system call performance + */ +#include "../perf.h" +#include "../util/util.h" +#include <subcmd/parse-options.h> +#include "../builtin.h" +#include "bench.h" + +#include <stdio.h> +#include <locale.h> +#include <sys/time.h> +#include <sys/syscall.h> + +#define LOOPS_DEFAULT 10000000 +static int loops = LOOPS_DEFAULT; + +static const struct option options[] = { + OPT_INTEGER('l', "loop", &loops, "Specify number of loops"), + OPT_END() +}; + +static const char * const bench_syscall_usage[] = { + "perf bench syscall <options>", + NULL +}; + +int bench_syscall_basic(int argc, const char **argv, const char *prefix __maybe_unused) +{ + struct timeval start, stop, diff; + unsigned long long result_usec = 0; + int i; + + argc = parse_options(argc, argv, options, bench_syscall_usage, 0); + + gettimeofday(&start, NULL); + + for (i = 0; i < loops; i++) + getppid(); + + gettimeofday(&stop, NULL); + timersub(&stop, &start, &diff); + + switch (bench_format) { + case BENCH_FORMAT_DEFAULT: + setlocale(LC_NUMERIC, ""); + printf("# Executed %'d getppid() calls\n", loops); + + result_usec = diff.tv_sec * 1000000; + result_usec += diff.tv_usec; + + printf(" %14s: %lu.%03lu [sec]\n\n", "Total time", + diff.tv_sec, + (unsigned long) (diff.tv_usec/1000)); + + printf(" %14lf usecs/op\n", + (double)result_usec / (double)loops); + printf(" %'14d ops/sec\n", + (int)((double)loops / + ((double)result_usec / (double)1000000))); + break; + + case BENCH_FORMAT_SIMPLE: + printf("%lu.%03lu\n", + diff.tv_sec, + (unsigned long) (diff.tv_usec / 1000)); + break; + + default: + /* reaching here is something disaster */ + fprintf(stderr, "Unknown format:%d\n", bench_format); + exit(1); + break; + } + + return 0; +} diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c index a1cddc6..f32a503 100644 --- a/tools/perf/builtin-bench.c +++ b/tools/perf/builtin-bench.c @@ -9,10 +9,11 @@ /* * Available benchmark collection list: * - * sched ... scheduler and IPC performance - * mem ... memory access performance - * numa ... NUMA scheduling and MM performance - * futex ... Futex performance + * sched ... Scheduler and IPC performance + * syscall ... System call performance + * mem ... Memory access performance + * numa ... NUMA scheduling and MM performance + * futex ... Futex performance */ #include "perf.h" #include "util/util.h" @@ -44,10 +45,16 @@ static struct bench numa_benchmarks[] = { static struct bench sched_benchmarks[] = { { "messaging", "Benchmark for scheduling and IPC", bench_sched_messaging }, { "pipe", "Benchmark for pipe() between two processes", bench_sched_pipe }, - { "all", "Run all scheduler benchmarks", NULL }, + { "all", "Run all scheduler benchmarks", NULL }, { NULL, NULL, NULL } }; +static struct bench syscall_benchmarks[] = { + { "basic", "Benchmark for basic getppid() system calls", bench_syscall_basic }, + { "all", "Run all syscall benchmarks", NULL }, + { NULL, NULL, NULL }, +}; + static struct bench mem_benchmarks[] = { { "memcpy", "Benchmark for memcpy() functions", bench_mem_memcpy }, { "memset", "Benchmark for memset() functions", bench_mem_memset }, @@ -74,6 +81,7 @@ struct collection { static struct collection collections[] = { { "sched", "Scheduler and IPC benchmarks", sched_benchmarks }, + { "syscall", "System call benchmarks", syscall_benchmarks }, { "mem", "Memory access benchmarks", mem_benchmarks }, #ifdef HAVE_LIBNUMA_SUPPORT { "numa", "NUMA scheduling and MM benchmarks", numa_benchmarks }, -- 2.4.11
| |