]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
perf script python: Allow reporting the [un]throttle PERF_RECORD_ meta event
authorStephen Brennan <stephen.s.brennan@oracle.com>
Wed, 1 Sep 2021 21:08:15 +0000 (14:08 -0700)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 3 Sep 2021 11:18:25 +0000 (08:18 -0300)
perf_events may sometimes throttle an event due to creating too many
samples during a given timer tick.

As of now, the perf tool will not report on throttling, which means this
is a silent error.

Implement a callback for the throttle and unthrottle events within the
Python scripting engine, which can allow scripts to detect and report
when events may have been lost due to throttling.

The simplest script to report throttle events is:

  def throttle(*args):
      print("throttle" + repr(args))

  def unthrottle(*args):
      print("unthrottle" + repr(args))

Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lore.kernel.org/lkml/20210901210815.133251-1-stephen.s.brennan@oracle.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/builtin-script.c
tools/perf/util/scripting-engines/trace-event-python.c
tools/perf/util/trace-event.h

index f469354155f12e855dec303117c7616c9d0743b7..0e824f7d8b19cd7b7b4dddcf200ae14f569cde94 100644 (file)
@@ -2492,6 +2492,17 @@ process_lost_event(struct perf_tool *tool,
                           sample->tid);
 }
 
+static int
+process_throttle_event(struct perf_tool *tool __maybe_unused,
+                      union perf_event *event,
+                      struct perf_sample *sample,
+                      struct machine *machine)
+{
+       if (scripting_ops && scripting_ops->process_throttle)
+               scripting_ops->process_throttle(event, sample, machine);
+       return 0;
+}
+
 static int
 process_finished_round_event(struct perf_tool *tool __maybe_unused,
                             union perf_event *event,
@@ -3652,6 +3663,8 @@ int cmd_script(int argc, const char **argv)
                        .stat_config     = process_stat_config_event,
                        .thread_map      = process_thread_map_event,
                        .cpu_map         = process_cpu_map_event,
+                       .throttle        = process_throttle_event,
+                       .unthrottle      = process_throttle_event,
                        .ordered_events  = true,
                        .ordering_requires_timestamps = true,
                },
index 69129e2aa7a18ac7c814ff06d66205b509ffda89..c0c010350bc2a1d9f218b75e19bd17565b2fb89d 100644 (file)
@@ -1422,6 +1422,37 @@ static void python_process_event(union perf_event *event,
        }
 }
 
+static void python_process_throttle(union perf_event *event,
+                                   struct perf_sample *sample,
+                                   struct machine *machine)
+{
+       const char *handler_name;
+       PyObject *handler, *t;
+
+       if (event->header.type == PERF_RECORD_THROTTLE)
+               handler_name = "throttle";
+       else
+               handler_name = "unthrottle";
+       handler = get_handler(handler_name);
+       if (!handler)
+               return;
+
+       t = tuple_new(6);
+       if (!t)
+               return;
+
+       tuple_set_u64(t, 0, event->throttle.time);
+       tuple_set_u64(t, 1, event->throttle.id);
+       tuple_set_u64(t, 2, event->throttle.stream_id);
+       tuple_set_s32(t, 3, sample->cpu);
+       tuple_set_s32(t, 4, sample->pid);
+       tuple_set_s32(t, 5, sample->tid);
+
+       call_object(handler, t, handler_name);
+
+       Py_DECREF(t);
+}
+
 static void python_do_process_switch(union perf_event *event,
                                     struct perf_sample *sample,
                                     struct machine *machine)
@@ -2079,5 +2110,6 @@ struct scripting_ops python_scripting_ops = {
        .process_auxtrace_error = python_process_auxtrace_error,
        .process_stat           = python_process_stat,
        .process_stat_interval  = python_process_stat_interval,
+       .process_throttle       = python_process_throttle,
        .generate_script        = python_generate_script,
 };
index 54aadeedf28c02bfac29e2c2355b7f98c972215a..6409811057888d3048c9097c7156b1a238f6dda4 100644 (file)
@@ -90,6 +90,9 @@ struct scripting_ops {
        void (*process_stat)(struct perf_stat_config *config,
                             struct evsel *evsel, u64 tstamp);
        void (*process_stat_interval)(u64 tstamp);
+       void (*process_throttle)(union perf_event *event,
+                                struct perf_sample *sample,
+                                struct machine *machine);
        int (*generate_script) (struct tep_handle *pevent, const char *outfile);
 };