From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753030AbbJYOyW (ORCPT ); Sun, 25 Oct 2015 10:54:22 -0400 Received: from mx1.redhat.com ([209.132.183.28]:59728 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752925AbbJYOxq (ORCPT ); Sun, 25 Oct 2015 10:53:46 -0400 From: Jiri Olsa To: Arnaldo Carvalho de Melo Cc: lkml , David Ahern , Ingo Molnar , Namhyung Kim , Peter Zijlstra , "Liang, Kan" Subject: [PATCH 51/52] perf script: Add python support for stat events Date: Sun, 25 Oct 2015 15:52:07 +0100 Message-Id: <1445784728-21732-52-git-send-email-jolsa@kernel.org> In-Reply-To: <1445784728-21732-1-git-send-email-jolsa@kernel.org> References: <1445784728-21732-1-git-send-email-jolsa@kernel.org> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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___[](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 meassured 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. Link: http://lkml.kernel.org/n/tip-jojiaelyckrw6040wqc06q1j@git.kernel.org Signed-off-by: Jiri Olsa --- .../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)); + + 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)); + + 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