Received: by 2002:a05:6a10:c604:0:0:0:0 with SMTP id y4csp3086925pxt; Mon, 9 Aug 2021 16:44:21 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyOo5l78+a8lHIT7pOgbpEOAR/MqSkyhW8EfzuDCYb9RHU2QVROl6shwB8lWTNDRIFXwXHd X-Received: by 2002:a05:6e02:ed1:: with SMTP id i17mr232377ilk.272.1628552661687; Mon, 09 Aug 2021 16:44:21 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1628552661; cv=none; d=google.com; s=arc-20160816; b=AB5a2k+F3/QMiMxhiYxkSYcxT2xavrBmIGhVZ4P0YKE4LEk9O/MoQ4KbQpgeyh+NkI AfCFu3Wu9Vmbd7mNscpOPUJaXv4tz9Ff8CjkGcDs6fd1rWyppe7t6KNOOb1HYhYAJGgr nxPEuapZUHhIYNPtixY2Iw+2pER3uWG1WM+3SntIsVNpx0iCy56Tsj9jcHfNzytQD/3Q ZqxC8qCMqzdYSXXRAQjEbFnqLxjpo0LrULtxLeW4R4Aoj9sBOzVPNB0h74E+XwV19bC0 yNY95qyu+I/FboqI3ToNFIvpm+lDaawf/Sw1ZOmSOFm1SJSz+QwLmhCccTGSWi3TIoWl wOxw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date:dkim-signature; bh=xzswtiIEM633nQQHQMOVh9/xGwpj3C9awhnJj0CjdUM=; b=ZDyZnHcEbGXVLLDFIOgV0eklyrL2PQHxL7Iv4f1SKPSUNTnmWqzuapFd1NZH78945r HdvgA0OphrzSV/kc62n2PQ16pxIEdWkC9TNcX42TSAd3lBtM0wugiTzdMz+czZfxh2bQ f3r3Z+tXZrcjfXRUOnNw4gN6wv4KVWF0QW/uMaRgicR4dbtC9R2rVSeT0t1mbdK1srnR ysTDo4ctY0/lU++7DwMBLKp6FOXu42yRvKZXoaOz4FOytmnZrolYNmnr9DOiCe3tD1M6 77vfDUsBac6qSaZbkYyHXZ2Xz4wrWvKQJEkegyLKF2GszHmAgUD8lM+O4I0mxkVwTQRa t78Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=eBuxhmxs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id i17si6939763jav.67.2021.08.09.16.44.10; Mon, 09 Aug 2021 16:44:21 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=eBuxhmxs; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234331AbhHIUX4 (ORCPT + 99 others); Mon, 9 Aug 2021 16:23:56 -0400 Received: from mail.kernel.org ([198.145.29.99]:37126 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233061AbhHIUXz (ORCPT ); Mon, 9 Aug 2021 16:23:55 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 291A36101E; Mon, 9 Aug 2021 20:23:34 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1628540614; bh=J5RaGWfrhprnHWMncCMmbDhppJOblEv5Du+oLkqkc3c=; h=Date:From:To:Cc:Subject:References:In-Reply-To:From; b=eBuxhmxszoqTClkIyNw5g/z7kQ/dR3PbYo+sH0lJRVDnHNERNlwGm9lZS2xev8zSX ftnXgFm/UuvHu0g4JwHCtnQ2XS4rXnQBlyNgFnk5EXIbJPo0uMSZgX6OTdzW60yC4W 8YrsAEJmp3w4c18ZewobKDaJ4+uOg1kp20XcuxD62TBOdst4Yk+snrpMXFs1fd2K6k qO9FqWTLf0mJJEgJurjFm5ZRQ97hSWlYbIJVSoKi/zH6WfXZkwxc40PfE9KIpxOcwo NWzH7Q7+eZuobvgk1KNEOwaOEet6rcAoHiLD6SU6XDq91ZuUn/ar7ltkwVbUfnv49t xgDk98/oM5doQ== Received: by quaco.ghostprotocols.net (Postfix, from userid 1000) id 7BB7A403F2; Mon, 9 Aug 2021 17:23:31 -0300 (-03) Date: Mon, 9 Aug 2021 17:23:31 -0300 From: Arnaldo Carvalho de Melo To: Riccardo Mancini Cc: Ian Rogers , Namhyung Kim , Peter Zijlstra , Ingo Molnar , Mark Rutland , Jiri Olsa , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org Subject: Re: [PATCH] perf bench: add benchmark for evlist open/close operations Message-ID: References: <20210809201101.277594-1-rickyman7@gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210809201101.277594-1-rickyman7@gmail.com> X-Url: http://acmel.wordpress.com Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Em Mon, Aug 09, 2021 at 10:11:02PM +0200, Riccardo Mancini escreveu: > This new benchmark finds the total time that is taken to open, mmap, > enable, disable, munmap, close an evlist (time taken for new, > create_maps, config, delete is not counted in). > The evlist can be configured as in perf-record using the > -a,-C,-e,-u,--per-thread,-t,-p options. > The events can be duplicated in the evlist to quickly test performance > with many events using the -n options. > Furthermore, also the number of iterations used to calculate the > statistics is customizable. > > Examples: > - Open one dummy event system-wide: > $ sudo ./perf bench internals evlist-open-close > Number of cpus: 4 > Number of threads: 1 > Number of events: 1 (4 fds) > Number of iterations: 100 > Average open-close took: 613.870 usec (+- 32.852 usec) > > - Open the group '{cs,cycles}' on CPU 0 > $ sudo ./perf bench internals evlist-open-close -e '{cs,cycles}' -C 0 > Number of cpus: 1 > Number of threads: 1 > Number of events: 2 (2 fds) > Number of iterations: 100 > Average open-close took: 8503.220 usec (+- 252.652 usec) > > - Open 10 'cycles' events for user 0, calculate average over 100 runs > $ sudo ./perf bench internals evlist-open-close -e cycles -n 10 -u 0 -i 100 > Number of cpus: 4 > Number of threads: 328 > Number of events: 10 (13120 fds) > Number of iterations: 100 > Average open-close took: 180043.140 usec (+- 2295.889 usec) > > Signed-off-by: Riccardo Mancini > --- > tools/perf/bench/Build | 1 + > tools/perf/bench/bench.h | 1 + > tools/perf/bench/evlist-open-close.c | 275 +++++++++++++++++++++++++++ > tools/perf/builtin-bench.c | 1 + > 4 files changed, 278 insertions(+) > create mode 100644 tools/perf/bench/evlist-open-close.c > > diff --git a/tools/perf/bench/Build b/tools/perf/bench/Build > index e43f46931b41b78f..61d45fcb4057c945 100644 > --- a/tools/perf/bench/Build > +++ b/tools/perf/bench/Build > @@ -13,6 +13,7 @@ perf-y += synthesize.o > perf-y += kallsyms-parse.o > perf-y += find-bit-bench.o > perf-y += inject-buildid.o > +perf-y += evlist-open-close.o > > perf-$(CONFIG_X86_64) += mem-memcpy-x86-64-asm.o > perf-$(CONFIG_X86_64) += mem-memset-x86-64-asm.o > diff --git a/tools/perf/bench/bench.h b/tools/perf/bench/bench.h > index eac36afab2b39fa5..b3480bc33fe84885 100644 > --- a/tools/perf/bench/bench.h > +++ b/tools/perf/bench/bench.h > @@ -48,6 +48,7 @@ int bench_epoll_ctl(int argc, const char **argv); > int bench_synthesize(int argc, const char **argv); > int bench_kallsyms_parse(int argc, const char **argv); > int bench_inject_build_id(int argc, const char **argv); > +int bench_evlist_open_close(int argc, const char **argv); > > #define BENCH_FORMAT_DEFAULT_STR "default" > #define BENCH_FORMAT_DEFAULT 0 > diff --git a/tools/perf/bench/evlist-open-close.c b/tools/perf/bench/evlist-open-close.c > new file mode 100644 > index 0000000000000000..40bce06f5ca7bef3 > --- /dev/null > +++ b/tools/perf/bench/evlist-open-close.c > @@ -0,0 +1,275 @@ > +// SPDX-License-Identifier: GPL-2.0 > +#include > +#include > +#include > +#include "bench.h" > +#include "../util/debug.h" > +#include "../util/stat.h" > +#include "../util/evlist.h" > +#include "../util/evsel.h" > +#include "../util/strbuf.h" > +#include "../util/record.h" > +#include "../util/parse-events.h" > +#include "internal/threadmap.h" > +#include "internal/cpumap.h" > +#include > +#include > +#include > +#include > +#include > + > +#define MMAP_FLUSH_DEFAULT 1 > + > +static int iterations = 100; > +static int nr_events = 1; > +static const char *event_string = "dummy"; > + > +static struct record_opts opts = { > + .sample_time = true, > + .mmap_pages = UINT_MAX, > + .user_freq = UINT_MAX, > + .user_interval = ULLONG_MAX, > + .freq = 4000, > + .target = { > + .uses_mmap = true, > + .default_per_cpu = true, > + }, > + .mmap_flush = MMAP_FLUSH_DEFAULT, > + .nr_threads_synthesize = 1, > + .ctl_fd = -1, > + .ctl_fd_ack = -1, > +}; > + > +static const struct option options[] = { > + OPT_STRING('e', "event", &event_string, "event", > + "event selector. use 'perf list' to list available events"), > + OPT_INTEGER('n', "nr-events", &nr_events, > + "number of dummy events to create (default 1). If used with -e, it clones those events n times (1 = no change)"), > + OPT_INTEGER('i', "iterations", &iterations, > + "Number of iterations used to compute average (default=100)"), > + OPT_BOOLEAN('a', "all-cpus", &opts.target.system_wide, > + "system-wide collection from all CPUs"), > + OPT_STRING('C', "cpu", &opts.target.cpu_list, "cpu", > + "list of cpus where to open events"), > + OPT_STRING('p', "pid", &opts.target.pid, "pid", > + "record events on existing process id"), > + OPT_STRING('t', "tid", &opts.target.tid, "tid", > + "record events on existing thread id"), > + OPT_STRING('u', "uid", &opts.target.uid_str, "user", > + "user to profile"), > + OPT_BOOLEAN(0, "per-thread", &opts.target.per_thread, > + "use per-thread mmaps"), > + OPT_END() > +}; > + > +static const char *const bench_usage[] = { > + "perf bench internals evlist-open-close ", > + NULL > +}; > + > +static int evlist__count_evsel_fds(struct evlist *evlist) > +{ > + struct evsel *evsel; > + int cnt = 0; > + > + evlist__for_each_entry(evlist, evsel) { > + cnt += evsel->core.threads->nr * evsel->core.cpus->nr; > + } > + > + return cnt; > +} > + > +static struct evlist *bench__create_evlist(char *evstr) > +{ > + struct evlist *evlist; > + struct parse_events_error err; > + int ret; > + > + evlist = evlist__new(); > + if (!evlist) { > + pr_err("Not enough memory to create evlist\n"); > + return NULL; > + } > + > + bzero(&err, sizeof(err)); man bzero The bzero() function is deprecated (marked as LEGACY in POSIX.1-2001); use memset(3) in new programs. POSIX.1-2008 removes the specification of bzero(). The bzero() function first appeared in 4.3BSD. I'm replacing it with a memset(). > + ret = parse_events(evlist, evstr, &err); > + if (ret) { > + parse_events_print_error(&err, evstr); > + pr_err("Run 'perf list' for a list of valid events\n"); > + ret = 1; > + goto out_delete_evlist; > + } > + > + ret = evlist__create_maps(evlist, &opts.target); > + if (ret < 0) { > + pr_err("Not enough memory to create thread/cpu maps\n"); > + goto out_delete_evlist; > + } > + > + evlist__config(evlist, &opts, NULL); > + > + return evlist; > + > +out_delete_evlist: > + evlist__delete(evlist); > + return NULL; > +} > + > +static int bench__do_evlist_open_close(struct evlist *evlist) > +{ > + int err = -1; > + char sbuf[STRERR_BUFSIZE]; > + > + err = evlist__open(evlist); > + if (err < 0) { > + pr_err("evlist__open: %s\n", > + str_error_r(errno, sbuf, sizeof(sbuf))); > + return err; > + } > + > + err = evlist__mmap(evlist, opts.mmap_pages); > + if (err < 0) { > + pr_err("evlist__mmap: %s\n", > + str_error_r(errno, sbuf, sizeof(sbuf))); > + return err; > + } > + > + evlist__enable(evlist); > + > + evlist__disable(evlist); > + evlist__munmap(evlist); > + evlist__close(evlist); > + > + return 0; > +} > + > +static int bench_evlist_open_close__run(char *evstr) > +{ > + struct evlist *evlist; > + struct timeval start, end, diff; > + double time_average, time_stddev; > + int i; > + int err; > + u64 runtime_us; > + struct stats time_stats; > + > + init_stats(&time_stats); > + > + // used to print statistics only > + evlist = bench__create_evlist(evstr); > + > + printf(" Number of cpus:\t%d\n", evlist->core.cpus->nr); > + printf(" Number of threads:\t%d\n", evlist->core.threads->nr); > + printf(" Number of events:\t%d (%d fds)\n", > + evlist->core.nr_entries, evlist__count_evsel_fds(evlist)); > + printf(" Number of iterations:\t%d\n", iterations); > + > + evlist__delete(evlist); > + > + for (i = 0; i < iterations; i++) { > + pr_debug("Started iteration %d\n", i); > + evlist = bench__create_evlist(evstr); > + gettimeofday(&start, NULL); > + err = bench__do_evlist_open_close(evlist); > + if (err) { > + evlist__delete(evlist); > + return err; > + } > + > + gettimeofday(&end, NULL); > + timersub(&end, &start, &diff); > + runtime_us = diff.tv_sec * USEC_PER_SEC + diff.tv_usec; > + update_stats(&time_stats, runtime_us); > + > + evlist__delete(evlist); > + pr_debug("Iteration %d took:\t%ldus\n", i, runtime_us); > + } > + > + time_average = avg_stats(&time_stats); > + time_stddev = stddev_stats(&time_stats); > + printf(" Average open-close took: %.3f usec (+- %.3f usec)\n", > + time_average, time_stddev); > + > + return 0; > +} > + > +static char *bench__repeat_event_string(const char *evstr, int n) > +{ > + int err, i, final_size, str_size; > + struct strbuf buf; > + char sbuf[STRERR_BUFSIZE]; > + > + str_size = strlen(evstr); > + final_size = str_size * n + n; > + > + err = strbuf_init(&buf, final_size); > + if (err) { > + pr_err("strbuf_init: %s\n", > + str_error_r(err, sbuf, sizeof(sbuf))); > + goto out_error; > + } > + > + for (i = 0; i < n; i++) { > + err = strbuf_add(&buf, evstr, str_size); > + if (err) { > + pr_err("strbuf_add: %s\n", > + str_error_r(err, sbuf, sizeof(sbuf))); > + goto out_error; > + } > + > + err = strbuf_addch(&buf, i == n-1 ? '\0' : ','); > + if (err) { > + pr_err("strbuf_addch: %s\n", > + str_error_r(err, sbuf, sizeof(sbuf))); > + goto out_error; > + } > + } > + > + return strbuf_detach(&buf, NULL); > + > +out_error: > + strbuf_release(&buf); > + return NULL; > +} > + > + > +int bench_evlist_open_close(int argc, const char **argv) > +{ > + int err = 0; > + char *evstr, errbuf[BUFSIZ]; > + > + argc = parse_options(argc, argv, options, bench_usage, 0); > + if (argc) { > + usage_with_options(bench_usage, options); > + exit(EXIT_FAILURE); > + } > + > + err = target__validate(&opts.target); > + if (err) { > + target__strerror(&opts.target, err, errbuf, BUFSIZ); > + pr_err("%s\n", errbuf); > + goto out; > + } > + > + err = target__parse_uid(&opts.target); > + if (err) { > + target__strerror(&opts.target, err, errbuf, BUFSIZ); > + pr_err("%s", errbuf); > + goto out; > + } > + > + /* Enable ignoring missing threads when -u/-p option is defined. */ > + opts.ignore_missing_thread = opts.target.uid != UINT_MAX || opts.target.pid; > + > + evstr = bench__repeat_event_string(event_string, nr_events); > + if (!evstr) { > + err = -ENOMEM; > + goto out; > + } > + > + err = bench_evlist_open_close__run(evstr); > + > + free(evstr); > +out: > + return err; > +} > diff --git a/tools/perf/builtin-bench.c b/tools/perf/builtin-bench.c > index 62a7b7420a448517..d0895162c2ba6411 100644 > --- a/tools/perf/builtin-bench.c > +++ b/tools/perf/builtin-bench.c > @@ -88,6 +88,7 @@ static struct bench internals_benchmarks[] = { > { "synthesize", "Benchmark perf event synthesis", bench_synthesize }, > { "kallsyms-parse", "Benchmark kallsyms parsing", bench_kallsyms_parse }, > { "inject-build-id", "Benchmark build-id injection", bench_inject_build_id }, > + { "evlist-open-close", "Benchmark evlist open and close", bench_evlist_open_close }, > { NULL, NULL, NULL } > }; > > -- > 2.31.1 > -- - Arnaldo