On Tue, Dec 08, 2020 at 10:16:46AM -0800, Song Liu wrote:
> Introduce perf-stat -b option, which counts events for BPF programs, like:
> 
> [root@localhost ~]# ~/perf stat -e ref-cycles,cycles -b 254 -I 1000
>      1.487903822            115,200      ref-cycles
>      1.487903822             86,012      cycles
>      2.489147029             80,560      ref-cycles
>      2.489147029             73,784      cycles
>      3.490341825             60,720      ref-cycles
>      3.490341825             37,797      cycles
>      4.491540887             37,120      ref-cycles
>      4.491540887             31,963      cycles
> 
> The example above counts cycles and ref-cycles of BPF program of id 254.
> This is similar to bpftool-prog-profile command, but more flexible.
> 
> perf-stat -b creates per-cpu perf_event and loads fentry/fexit BPF
> programs (monitor-progs) to the target BPF program (target-prog). The
> monitor-progs read perf_event before and after the target-prog, and
> aggregate the difference in a BPF map. Then the user space reads data
> from these maps.
> 
> A new struct bpf_counter is introduced to provide common interface that
> uses BPF programs/maps to count perf events.
> 
> Signed-off-by: Song Liu <songliubrav...@fb.com>

I'm getting this at the end of the compilation:

  LINK     perf
rm /home/jolsa/linux-perf/tools/perf/util/bpf_skel/.tmp/bpf_prog_profiler.bpf.o

I guess we can keep it or make it silent somehow

> ---
>  tools/perf/Makefile.perf                      |   2 +-
>  tools/perf/builtin-stat.c                     |  77 ++++-
>  tools/perf/util/Build                         |   1 +
>  tools/perf/util/bpf_counter.c                 | 297 ++++++++++++++++++
>  tools/perf/util/bpf_counter.h                 |  73 +++++
>  .../util/bpf_skel/bpf_prog_profiler.bpf.c     |  93 ++++++
>  tools/perf/util/evsel.c                       |  11 +
>  tools/perf/util/evsel.h                       |   6 +
>  tools/perf/util/stat-display.c                |   4 +-
>  tools/perf/util/target.c                      |  34 +-
>  tools/perf/util/target.h                      |  10 +
>  11 files changed, 591 insertions(+), 17 deletions(-)
>  create mode 100644 tools/perf/util/bpf_counter.c
>  create mode 100644 tools/perf/util/bpf_counter.h
>  create mode 100644 tools/perf/util/bpf_skel/bpf_prog_profiler.bpf.c

we need man page update, would be great with some example

SNIP

> -     int status = -EINVAL, run_idx;
> +     int status = -EINVAL, run_idx, err;
>       const char *mode;
>       FILE *output = stderr;
>       unsigned int interval, timeout;
>       const char * const stat_subcommands[] = { "record", "report" };
> +     char errbuf[BUFSIZ];
>  
>       setlocale(LC_ALL, "");
>  
> @@ -2169,6 +2213,12 @@ int cmd_stat(int argc, const char **argv)
>       } else if (big_num_opt == 0) /* User passed --no-big-num */
>               stat_config.big_num = false;
>  
> +     err = target__validate(&target);
> +     if (err) {
> +             target__strerror(&target, err, errbuf, BUFSIZ);
> +             pr_warning("%s\n", errbuf);
> +     }
> +

is there a reason for this to move before setup_system_wide?

I don't think it's a big deal, but just curious if that's intentional

SNIP

> +
> +int bpf_counter__enable(struct evsel *evsel)
> +{
> +     if (list_empty(&evsel->bpf_counter_list))
> +             return 0;
> +     return evsel->bpf_counter_ops->enable(evsel);
> +}
> +
> +int bpf_counter__read(struct evsel *evsel)
> +{
> +     if (list_empty(&evsel->bpf_counter_list))
> +             return -EAGAIN;
> +     return evsel->bpf_counter_ops->read(evsel);
> +}
> +
> +int bpf_counter__destroy(struct evsel *evsel)
> +{

this could return void

SNIP

> @@ -247,6 +252,7 @@ void evsel__init(struct evsel *evsel,
>       evsel->bpf_obj     = NULL;
>       evsel->bpf_fd      = -1;
>       INIT_LIST_HEAD(&evsel->config_terms);
> +     INIT_LIST_HEAD(&evsel->bpf_counter_list);
>       perf_evsel__object.init(evsel);
>       evsel->sample_size = __evsel__sample_size(attr->sample_type);
>       evsel__calc_id_pos(evsel);
> @@ -1365,6 +1371,7 @@ void evsel__exit(struct evsel *evsel)
>  {
>       assert(list_empty(&evsel->core.node));
>       assert(evsel->evlist == NULL);
> +     bpf_counter__destroy(evsel);
>       evsel__free_counts(evsel);
>       perf_evsel__free_fd(&evsel->core);
>       perf_evsel__free_id(&evsel->core);
> @@ -1770,6 +1777,8 @@ static int evsel__open_cpu(struct evsel *evsel, struct 
> perf_cpu_map *cpus,
>               evsel->core.attr.sample_id_all = 0;
>  
>       display_attr(&evsel->core.attr);
> +     if (!list_empty(&evsel->bpf_counter_list))
> +             evsel->core.attr.inherit = 0;

I think this should go to evsel__config where we set all attr bits

thanks,
jirka

Reply via email to