On Tue, Dec 22, 2015 at 04:43:33PM +0100, Jiri Olsa wrote: > Add support to get stat events data in perf python scripts. > > The python script shall implement 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. > > Tested-by: Kan Liang <kan.li...@intel.com> > Link: http://lkml.kernel.org/n/tip-jojiaelyckrw6040wqc06...@git.kernel.org > Signed-off-by: Jiri Olsa <jo...@kernel.org> > --- > .../util/scripting-engines/trace-event-python.c | 114 > +++++++++++++++++++-- > 1 file changed, 108 insertions(+), 6 deletions(-) > > diff --git a/tools/perf/util/scripting-engines/trace-event-python.c > b/tools/perf/util/scripting-engines/trace-event-python.c > index a8e825fca42a..8436eb23eb16 100644 > --- a/tools/perf/util/scripting-engines/trace-event-python.c > +++ b/tools/perf/util/scripting-engines/trace-event-python.c > @@ -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,103 @@ 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 time, > + 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)); > + PyTuple_SetItem(t, n++, PyLong_FromLong(time)); > + PyTuple_SetItem(t, n++, PyLong_FromLong(count->val)); > + PyTuple_SetItem(t, n++, PyLong_FromLong(count->ena)); > + PyTuple_SetItem(t, n++, PyLong_FromLong(count->run));
What about 32-bit systems? It seems the PyLong_FromLong() takes long but the counts are u64. > + > + 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 time) > +{ > + 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, time, > + &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), time, > + perf_counts(counter->counts, cpu, thread)); > + } > + } > +} > + > +static void python_process_stat_interval(u64 time) > +{ > + 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; > + } > + > + PyTuple_SetItem(t, n++, PyLong_FromLong(time)); Ditto. Thanks, Namhyung > + > + 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 +1301,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, > }; > -- > 2.4.3 > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/