Commit aef90263 authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo

perf script: Add python support for stat events

Add support to get stat events data in perf python scripts.

The python script shall implement the following new interface to process
stat data:

  def stat__<event_name>_[<modifier>](cpu, thread, time, val, ena, run):

    - is called for every stat event for given counter,
      if user monitors 'cycles,instructions:u" following
      callbacks should be defined:

      def stat__cycles(cpu, thread, time, val, ena, run):
      def stat__instructions_u(cpu, thread, time, val, ena, run):

  def stat__interval(time):

    - is called for every interval with its time,
      in non interval mode it's called after last
      stat event with total measured time in ns

The rest of the current interface stays untouched..

Please check example CPI metrics script in following patch
with command line examples in changelogs.
Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarKan Liang <kan.liang@intel.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1452028152-26762-8-git-send-email-jolsa@kernel.org
[ Rename 'time' parameters to 'tstamp', to fix the build in older distros ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent e099eba8
...@@ -41,6 +41,9 @@ ...@@ -41,6 +41,9 @@
#include "../thread-stack.h" #include "../thread-stack.h"
#include "../trace-event.h" #include "../trace-event.h"
#include "../machine.h" #include "../machine.h"
#include "thread_map.h"
#include "cpumap.h"
#include "stat.h"
PyMODINIT_FUNC initperf_trace_context(void); PyMODINIT_FUNC initperf_trace_context(void);
...@@ -859,6 +862,104 @@ static void python_process_event(union perf_event *event, ...@@ -859,6 +862,104 @@ static void python_process_event(union perf_event *event,
} }
} }
static void get_handler_name(char *str, size_t size,
struct perf_evsel *evsel)
{
char *p = str;
scnprintf(str, size, "stat__%s", perf_evsel__name(evsel));
while ((p = strchr(p, ':'))) {
*p = '_';
p++;
}
}
static void
process_stat(struct perf_evsel *counter, int cpu, int thread, u64 tstamp,
struct perf_counts_values *count)
{
PyObject *handler, *t;
static char handler_name[256];
int n = 0;
t = PyTuple_New(MAX_FIELDS);
if (!t)
Py_FatalError("couldn't create Python tuple");
get_handler_name(handler_name, sizeof(handler_name),
counter);
handler = get_handler(handler_name);
if (!handler) {
pr_debug("can't find python handler %s\n", handler_name);
return;
}
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(thread));
tuple_set_u64(t, n++, tstamp);
tuple_set_u64(t, n++, count->val);
tuple_set_u64(t, n++, count->ena);
tuple_set_u64(t, n++, count->run);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
call_object(handler, t, handler_name);
Py_DECREF(t);
}
static void python_process_stat(struct perf_stat_config *config,
struct perf_evsel *counter, u64 tstamp)
{
struct thread_map *threads = counter->threads;
struct cpu_map *cpus = counter->cpus;
int cpu, thread;
if (config->aggr_mode == AGGR_GLOBAL) {
process_stat(counter, -1, -1, tstamp,
&counter->counts->aggr);
return;
}
for (thread = 0; thread < threads->nr; thread++) {
for (cpu = 0; cpu < cpus->nr; cpu++) {
process_stat(counter, cpus->map[cpu],
thread_map__pid(threads, thread), tstamp,
perf_counts(counter->counts, cpu, thread));
}
}
}
static void python_process_stat_interval(u64 tstamp)
{
PyObject *handler, *t;
static const char handler_name[] = "stat__interval";
int n = 0;
t = PyTuple_New(MAX_FIELDS);
if (!t)
Py_FatalError("couldn't create Python tuple");
handler = get_handler(handler_name);
if (!handler) {
pr_debug("can't find python handler %s\n", handler_name);
return;
}
tuple_set_u64(t, n++, tstamp);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
call_object(handler, t, handler_name);
Py_DECREF(t);
}
static int run_start_sub(void) static int run_start_sub(void)
{ {
main_module = PyImport_AddModule("__main__"); main_module = PyImport_AddModule("__main__");
...@@ -1201,10 +1302,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile) ...@@ -1201,10 +1302,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
} }
struct scripting_ops python_scripting_ops = { struct scripting_ops python_scripting_ops = {
.name = "Python", .name = "Python",
.start_script = python_start_script, .start_script = python_start_script,
.flush_script = python_flush_script, .flush_script = python_flush_script,
.stop_script = python_stop_script, .stop_script = python_stop_script,
.process_event = python_process_event, .process_event = python_process_event,
.generate_script = python_generate_script, .process_stat = python_process_stat,
.process_stat_interval = python_process_stat_interval,
.generate_script = python_generate_script,
}; };
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment