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: Jiri Olsa <jolsa@kernel.org> Tested-by: Kan 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: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
parent
e099eba8c8
commit
aef9026356
|
@ -41,6 +41,9 @@
|
|||
#include "../thread-stack.h"
|
||||
#include "../trace-event.h"
|
||||
#include "../machine.h"
|
||||
#include "thread_map.h"
|
||||
#include "cpumap.h"
|
||||
#include "stat.h"
|
||||
|
||||
PyMODINIT_FUNC initperf_trace_context(void);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
main_module = PyImport_AddModule("__main__");
|
||||
|
@ -1201,10 +1302,12 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
|
|||
}
|
||||
|
||||
struct scripting_ops python_scripting_ops = {
|
||||
.name = "Python",
|
||||
.start_script = python_start_script,
|
||||
.flush_script = python_flush_script,
|
||||
.stop_script = python_stop_script,
|
||||
.process_event = python_process_event,
|
||||
.generate_script = python_generate_script,
|
||||
.name = "Python",
|
||||
.start_script = python_start_script,
|
||||
.flush_script = python_flush_script,
|
||||
.stop_script = python_stop_script,
|
||||
.process_event = python_process_event,
|
||||
.process_stat = python_process_stat,
|
||||
.process_stat_interval = python_process_stat_interval,
|
||||
.generate_script = python_generate_script,
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue