perf evsel: Introduce per event max_events property
authorArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 19 Oct 2018 18:47:34 +0000 (15:47 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 19 Oct 2018 19:31:09 +0000 (16:31 -0300)
This simply adds the field to 'struct perf_evsel' and allows setting
it via the event parser, to test it lets trace trace:

First look at where in a function that receives an evsel we can put a probe
to read how evsel->max_events was setup:

  # perf probe -x ~/bin/perf -L trace__event_handler
  <trace__event_handler@/home/acme/git/perf/tools/perf/builtin-trace.c:0>
        0  static int trace__event_handler(struct trace *trace, struct perf_evsel *evsel,
                                          union perf_event *event __maybe_unused,
                                          struct perf_sample *sample)
        3  {
        4         struct thread *thread = machine__findnew_thread(trace->host, sample->pid, sample->tid);
        5         int callchain_ret = 0;

        7         if (sample->callchain) {
        8                 callchain_ret = trace__resolve_callchain(trace, evsel, sample, &callchain_cursor);
        9                 if (callchain_ret == 0) {
       10                         if (callchain_cursor.nr < trace->min_stack)
       11                                 goto out;
       12                         callchain_ret = 1;
                          }
                  }

See what variables we can probe at line 7:

  # perf probe -x ~/bin/perf -V trace__event_handler:7
  Available variables at trace__event_handler:7
          @<trace__event_handler+89>
                  int     callchain_ret
                  struct perf_evsel*      evsel
                  struct perf_sample*     sample
                  struct thread*  thread
                  struct trace*   trace
                  union perf_event*       event

Add a probe at that line asking for evsel->max_events to be collected and named
as "max_events":

  # perf probe -x ~/bin/perf trace__event_handler:7 'max_events=evsel->max_events'
  Added new event:
    probe_perf:trace__event_handler (on trace__event_handler:7 in /home/acme/bin/perf with max_events=evsel->max_events)

  You can now use it in all perf tools, such as:

   perf record -e probe_perf:trace__event_handler -aR sleep 1

Now use 'perf trace', here aliased to just 'trace' and trace trace, i.e.
the first 'trace' is tracing just that 'probe_perf:trace__event_handler' event,
while the traced trace is tracing all scheduler tracepoints, will stop at two
events (--max-events 2) and will just set evsel->max_events for all the sched
tracepoints to 9, we will see the output of both traces intermixed:

  # trace -e *perf:*event_handler trace --max-events 2 -e sched:*/nr=9/
       0.000 :0/0 sched:sched_waking:comm=rcu_sched pid=10 prio=120 target_cpu=000
       0.009 :0/0 sched:sched_wakeup:comm=rcu_sched pid=10 prio=120 target_cpu=000
       0.000 trace/23949 probe_perf:trace__event_handler:(48c34a) max_events=0x9
       0.046 trace/23949 probe_perf:trace__event_handler:(48c34a) max_events=0x9
  #

Now, if the traced trace sends its output to /dev/null, we'll see just
what the first level trace outputs: that evsel->max_events is indeed
being set to 9:

  # trace -e *perf:*event_handler trace -o /dev/null --max-events 2 -e sched:*/nr=9/
       0.000 trace/23961 probe_perf:trace__event_handler:(48c34a) max_events=0x9
       0.030 trace/23961 probe_perf:trace__event_handler:(48c34a) max_events=0x9
  #

Now that we can set evsel->max_events, we can go to the next step, honour that
per-event property in 'perf trace'.

Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Milian Wolff <milian.wolff@kdab.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Wang Nan <wangnan0@huawei.com>
Link: https://lkml.kernel.org/n/tip-og00yasj276joem6e14l1eas@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/evsel.c
tools/perf/util/evsel.h
tools/perf/util/parse-events.c
tools/perf/util/parse-events.h
tools/perf/util/parse-events.l

index 29d7b97f66fbc5ae8efe67d3880263711d0a4d1a..7e95ec1c19a828cfdce2a7755f11bcb7b89e4f55 100644 (file)
@@ -232,6 +232,7 @@ void perf_evsel__init(struct perf_evsel *evsel,
        evsel->leader      = evsel;
        evsel->unit        = "";
        evsel->scale       = 1.0;
+       evsel->max_events  = ULONG_MAX;
        evsel->evlist      = NULL;
        evsel->bpf_fd      = -1;
        INIT_LIST_HEAD(&evsel->node);
@@ -793,6 +794,9 @@ static void apply_config_terms(struct perf_evsel *evsel,
                case PERF_EVSEL__CONFIG_TERM_MAX_STACK:
                        max_stack = term->val.max_stack;
                        break;
+               case PERF_EVSEL__CONFIG_TERM_MAX_EVENTS:
+                       evsel->max_events = term->val.max_events;
+                       break;
                case PERF_EVSEL__CONFIG_TERM_INHERIT:
                        /*
                         * attr->inherit should has already been set by
index 4107c39f4a54a97c7d3155a34e2814696e4ad21d..ad5d615c6db6494dc499e77fe1a71aecb0e49b64 100644 (file)
@@ -46,6 +46,7 @@ enum term_type {
        PERF_EVSEL__CONFIG_TERM_STACK_USER,
        PERF_EVSEL__CONFIG_TERM_INHERIT,
        PERF_EVSEL__CONFIG_TERM_MAX_STACK,
+       PERF_EVSEL__CONFIG_TERM_MAX_EVENTS,
        PERF_EVSEL__CONFIG_TERM_OVERWRITE,
        PERF_EVSEL__CONFIG_TERM_DRV_CFG,
        PERF_EVSEL__CONFIG_TERM_BRANCH,
@@ -65,6 +66,7 @@ struct perf_evsel_config_term {
                bool    inherit;
                bool    overwrite;
                char    *branch;
+               unsigned long max_events;
        } val;
        bool weak;
 };
@@ -99,6 +101,7 @@ struct perf_evsel {
        struct perf_counts      *prev_raw_counts;
        int                     idx;
        u32                     ids;
+       unsigned long           max_events;
        char                    *name;
        double                  scale;
        const char              *unit;
index f8cd3e7c918668cc1f593b539c6648d16b091726..59be3466d64d329ae50b9d719836f5ddbb780832 100644 (file)
@@ -926,6 +926,7 @@ static const char *config_term_names[__PARSE_EVENTS__TERM_TYPE_NR] = {
        [PARSE_EVENTS__TERM_TYPE_NOINHERIT]             = "no-inherit",
        [PARSE_EVENTS__TERM_TYPE_INHERIT]               = "inherit",
        [PARSE_EVENTS__TERM_TYPE_MAX_STACK]             = "max-stack",
+       [PARSE_EVENTS__TERM_TYPE_MAX_EVENTS]            = "nr",
        [PARSE_EVENTS__TERM_TYPE_OVERWRITE]             = "overwrite",
        [PARSE_EVENTS__TERM_TYPE_NOOVERWRITE]           = "no-overwrite",
        [PARSE_EVENTS__TERM_TYPE_DRV_CFG]               = "driver-config",
@@ -1037,6 +1038,9 @@ do {                                                                         \
        case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
                CHECK_TYPE_VAL(NUM);
                break;
+       case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
+               CHECK_TYPE_VAL(NUM);
+               break;
        default:
                err->str = strdup("unknown term");
                err->idx = term->err_term;
@@ -1084,6 +1088,7 @@ static int config_term_tracepoint(struct perf_event_attr *attr,
        case PARSE_EVENTS__TERM_TYPE_INHERIT:
        case PARSE_EVENTS__TERM_TYPE_NOINHERIT:
        case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
+       case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
        case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
        case PARSE_EVENTS__TERM_TYPE_NOOVERWRITE:
                return config_term_common(attr, term, err);
@@ -1162,6 +1167,9 @@ do {                                                              \
                case PARSE_EVENTS__TERM_TYPE_MAX_STACK:
                        ADD_CONFIG_TERM(MAX_STACK, max_stack, term->val.num);
                        break;
+               case PARSE_EVENTS__TERM_TYPE_MAX_EVENTS:
+                       ADD_CONFIG_TERM(MAX_EVENTS, max_events, term->val.num);
+                       break;
                case PARSE_EVENTS__TERM_TYPE_OVERWRITE:
                        ADD_CONFIG_TERM(OVERWRITE, overwrite, term->val.num ? 1 : 0);
                        break;
index 4473dac27aee254fd6752cb06d9b7877a1ffdaeb..5ed035cbcbb72dcbcf5c73d39be2248c099e7452 100644 (file)
@@ -71,6 +71,7 @@ enum {
        PARSE_EVENTS__TERM_TYPE_NOINHERIT,
        PARSE_EVENTS__TERM_TYPE_INHERIT,
        PARSE_EVENTS__TERM_TYPE_MAX_STACK,
+       PARSE_EVENTS__TERM_TYPE_MAX_EVENTS,
        PARSE_EVENTS__TERM_TYPE_NOOVERWRITE,
        PARSE_EVENTS__TERM_TYPE_OVERWRITE,
        PARSE_EVENTS__TERM_TYPE_DRV_CFG,
index 5f761f3ed0f3333fba455be4e2fa447282005e51..7805c71aaae2e53dbc74c072b4e5eb2a73e6c23a 100644 (file)
@@ -269,6 +269,7 @@ time                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_TIME); }
 call-graph             { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CALLGRAPH); }
 stack-size             { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_STACKSIZE); }
 max-stack              { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_STACK); }
+nr                     { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_MAX_EVENTS); }
 inherit                        { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_INHERIT); }
 no-inherit             { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_NOINHERIT); }
 overwrite              { return term(yyscanner, PARSE_EVENTS__TERM_TYPE_OVERWRITE); }