[PATCH 1/1] perf script python: Garbled text in tracepoint fields

2017-08-11 Thread Arun Kalyanasundaram
Pass the exact length of the string to is_printable_array instead of the
entire field size.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 tools/perf/util/scripting-engines/trace-event-python.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index c7187f067d31..45cc0c6635bb 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -601,6 +601,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
for (field = event->format.fields; field; field = field->next) {
unsigned int offset, len;
unsigned long long val;
+   char *end_ptr = NULL;
 
if (field->flags & FIELD_IS_ARRAY) {
offset = field->offset;
@@ -612,8 +613,12 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
len = offset >> 16;
offset &= 0x;
}
-   if (field->flags & FIELD_IS_STRING &&
-   is_printable_array(data + offset, len)) {
+   /* field may contain unused chars after the null char */
+   if (field->flags & FIELD_IS_STRING)
+   end_ptr = memchr(data + offset, '\0', len);
+   if (end_ptr &&
+   is_printable_array(data + offset,
+   (int)(end_ptr - ((char *)data + offset)) + 1)) {
obj = PyString_FromString((char *) data + 
offset);
} else {
obj = PyByteArray_FromStringAndSize((const char 
*) data + offset, len);
-- 
2.14.0.434.g98096fd7a8-goog



[PATCH 1/1] perf script python: Garbled text in tracepoint fields

2017-08-11 Thread Arun Kalyanasundaram
Pass the exact length of the string to is_printable_array instead of the
entire field size.

Signed-off-by: Arun Kalyanasundaram 
---
 tools/perf/util/scripting-engines/trace-event-python.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index c7187f067d31..45cc0c6635bb 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -601,6 +601,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
for (field = event->format.fields; field; field = field->next) {
unsigned int offset, len;
unsigned long long val;
+   char *end_ptr = NULL;
 
if (field->flags & FIELD_IS_ARRAY) {
offset = field->offset;
@@ -612,8 +613,12 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
len = offset >> 16;
offset &= 0x;
}
-   if (field->flags & FIELD_IS_STRING &&
-   is_printable_array(data + offset, len)) {
+   /* field may contain unused chars after the null char */
+   if (field->flags & FIELD_IS_STRING)
+   end_ptr = memchr(data + offset, '\0', len);
+   if (end_ptr &&
+   is_printable_array(data + offset,
+   (int)(end_ptr - ((char *)data + offset)) + 1)) {
obj = PyString_FromString((char *) data + 
offset);
} else {
obj = PyByteArray_FromStringAndSize((const char 
*) data + offset, len);
-- 
2.14.0.434.g98096fd7a8-goog



[PATCH 0/1] perf script python: Garbled text in tracepoint fields

2017-08-11 Thread Arun Kalyanasundaram
The string stored in some of the fields of tracepoint handlers has unused 
non-ascii characters beyond the first null ternimating character. As a result 
the call to is_printable_array fails and the python handlers receive the entire 
field as a byte array instead of just the subset of chars that represent the 
string.

This change calls is_printable_array with the correct length of the string 
instead of the entire field size.

Bug report: lkml/2017/7/18/228

Arun Kalyanasundaram (1):
  perf script python: Garbled text in tracepoint fields

 tools/perf/util/scripting-engines/trace-event-python.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

-- 
2.14.0.434.g98096fd7a8-goog



[PATCH 0/1] perf script python: Garbled text in tracepoint fields

2017-08-11 Thread Arun Kalyanasundaram
The string stored in some of the fields of tracepoint handlers has unused 
non-ascii characters beyond the first null ternimating character. As a result 
the call to is_printable_array fails and the python handlers receive the entire 
field as a byte array instead of just the subset of chars that represent the 
string.

This change calls is_printable_array with the correct length of the string 
instead of the entire field size.

Bug report: lkml/2017/7/18/228

Arun Kalyanasundaram (1):
  perf script python: Garbled text in tracepoint fields

 tools/perf/util/scripting-engines/trace-event-python.c | 9 +++--
 1 file changed, 7 insertions(+), 2 deletions(-)

-- 
2.14.0.434.g98096fd7a8-goog



[tip:perf/core] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  f38d281663b011d1d8a1b0119bb8357706d134a8
Gitweb: http://git.kernel.org/tip/f38d281663b011d1d8a1b0119bb8357706d134a8
Author: Arun Kalyanasundaram <arunk...@google.com>
AuthorDate: Fri, 21 Jul 2017 15:04:21 -0700
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Tue, 25 Jul 2017 22:43:20 -0300

perf script python: Add perf_sample dict to tracepoint handlers

The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Carrillo-Cisneros <davi...@google.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Seongjae Park <sj38.p...@gmail.com>
Cc: Stephane Eranian <eran...@google.com>
Link: http://lkml.kernel.org/r/20170721220422.63962-5-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 .../util/scripting-engines/trace-event-python.c| 41 +-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a4578..938b39f 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+   /* Need an additional reference for the perf_sample dict */
+   Py_INCREF(callchain);
 
if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   } else {
+   Py_DECREF(callchain);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 


[tip:perf/core] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  f38d281663b011d1d8a1b0119bb8357706d134a8
Gitweb: http://git.kernel.org/tip/f38d281663b011d1d8a1b0119bb8357706d134a8
Author: Arun Kalyanasundaram 
AuthorDate: Fri, 21 Jul 2017 15:04:21 -0700
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 25 Jul 2017 22:43:20 -0300

perf script python: Add perf_sample dict to tracepoint handlers

The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram 
Acked-by: Jiri Olsa 
Cc: Alexander Shishkin 
Cc: Daniel Borkmann 
Cc: David Carrillo-Cisneros 
Cc: David S. Miller 
Cc: Peter Zijlstra 
Cc: Seongjae Park 
Cc: Stephane Eranian 
Link: http://lkml.kernel.org/r/20170721220422.63962-5-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 .../util/scripting-engines/trace-event-python.c| 41 +-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a4578..938b39f 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+   /* Need an additional reference for the perf_sample dict */
+   Py_INCREF(callchain);
 
if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   } else {
+   Py_DECREF(callchain);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 


[tip:perf/core] perf script python: Generate hooks with additional argument

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  a641860550f05a4b8889dca61aab73c84b2d5e16
Gitweb: http://git.kernel.org/tip/a641860550f05a4b8889dca61aab73c84b2d5e16
Author: Arun Kalyanasundaram <arunk...@google.com>
AuthorDate: Fri, 21 Jul 2017 15:04:22 -0700
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Tue, 25 Jul 2017 22:43:21 -0300

perf script python: Generate hooks with additional argument

Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Carrillo-Cisneros <davi...@google.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Seongjae Park <sj38.p...@gmail.com>
Cc: Stephane Eranian <eran...@google.com>
Link: http://lkml.kernel.org/r/20170721220422.63962-6-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 .../util/scripting-engines/trace-event-python.c| 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 938b39f..c7187f0 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1367,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1436,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1446,15 +1455,20 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
-   "(event_name, cpu, secs, nsecs, pid, comm),\n");
+   "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
 
fclose(ofp);
 


[tip:perf/core] perf script python: Generate hooks with additional argument

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  a641860550f05a4b8889dca61aab73c84b2d5e16
Gitweb: http://git.kernel.org/tip/a641860550f05a4b8889dca61aab73c84b2d5e16
Author: Arun Kalyanasundaram 
AuthorDate: Fri, 21 Jul 2017 15:04:22 -0700
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 25 Jul 2017 22:43:21 -0300

perf script python: Generate hooks with additional argument

Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram 
Acked-by: Jiri Olsa 
Cc: Alexander Shishkin 
Cc: Daniel Borkmann 
Cc: David Carrillo-Cisneros 
Cc: David S. Miller 
Cc: Peter Zijlstra 
Cc: Seongjae Park 
Cc: Stephane Eranian 
Link: http://lkml.kernel.org/r/20170721220422.63962-6-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 .../util/scripting-engines/trace-event-python.c| 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 938b39f..c7187f0 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1367,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1436,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1446,15 +1455,20 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
-   "(event_name, cpu, secs, nsecs, pid, comm),\n");
+   "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
 
fclose(ofp);
 


[tip:perf/core] perf script python: Add sample_read to dict

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  74ec14f3893c3065053b91cec850cffa2d565e0a
Gitweb: http://git.kernel.org/tip/74ec14f3893c3065053b91cec850cffa2d565e0a
Author: Arun Kalyanasundaram <arunk...@google.com>
AuthorDate: Fri, 21 Jul 2017 15:04:20 -0700
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Tue, 25 Jul 2017 22:43:19 -0300

perf script python: Add sample_read to dict

Provide time_enabled, time_running and counter value in the perf_sample
dict.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Carrillo-Cisneros <davi...@google.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Seongjae Park <sj38.p...@gmail.com>
Cc: Stephane Eranian <eran...@google.com>
Link: http://lkml.kernel.org/r/20170721220422.63962-4-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 .../util/scripting-engines/trace-event-python.c| 51 ++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6d..55a4578 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,56 @@ exit:
return pylist;
 }
 
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+   PyObject *t;
+
+   t = PyTuple_New(2);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+   PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+   PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+   return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+struct perf_sample *sample,
+struct perf_evsel *evsel)
+{
+   u64 read_format = evsel->attr.read_format;
+   PyObject *values;
+   unsigned int i;
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+   pydict_set_item_string_decref(dict_sample, "time_enabled",
+   PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+   }
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+   pydict_set_item_string_decref(dict_sample, "time_running",
+   PyLong_FromUnsignedLongLong(sample->read.time_running));
+   }
+
+   if (read_format & PERF_FORMAT_GROUP)
+   values = PyList_New(sample->read.group.nr);
+   else
+   values = PyList_New(1);
+
+   if (!values)
+   Py_FatalError("couldn't create Python list");
+
+   if (read_format & PERF_FORMAT_GROUP) {
+   for (i = 0; i < sample->read.group.nr; i++) {
+   PyObject *t = 
get_sample_value_as_tuple(>read.group.values[i]);
+   PyList_SET_ITEM(values, i, t);
+   }
+   } else {
+   PyObject *t = get_sample_value_as_tuple(>read.one);
+   PyList_SET_ITEM(values, 0, t);
+   }
+   pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
 static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 struct perf_evsel *evsel,
 struct addr_location *al,
@@ -422,6 +472,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample 
*sample,
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
PyLong_FromUnsignedLongLong(sample->period));
+   set_sample_read_in_dict(dict_sample, sample, evsel);
pydict_set_item_string_decref(dict, "sample", dict_sample);
 
pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(


[tip:perf/core] perf script python: Add sample_read to dict

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  74ec14f3893c3065053b91cec850cffa2d565e0a
Gitweb: http://git.kernel.org/tip/74ec14f3893c3065053b91cec850cffa2d565e0a
Author: Arun Kalyanasundaram 
AuthorDate: Fri, 21 Jul 2017 15:04:20 -0700
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 25 Jul 2017 22:43:19 -0300

perf script python: Add sample_read to dict

Provide time_enabled, time_running and counter value in the perf_sample
dict.

Signed-off-by: Arun Kalyanasundaram 
Acked-by: Jiri Olsa 
Cc: Alexander Shishkin 
Cc: Daniel Borkmann 
Cc: David Carrillo-Cisneros 
Cc: David S. Miller 
Cc: Peter Zijlstra 
Cc: Seongjae Park 
Cc: Stephane Eranian 
Link: http://lkml.kernel.org/r/20170721220422.63962-4-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 .../util/scripting-engines/trace-event-python.c| 51 ++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6d..55a4578 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,56 @@ exit:
return pylist;
 }
 
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+   PyObject *t;
+
+   t = PyTuple_New(2);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+   PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+   PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+   return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+struct perf_sample *sample,
+struct perf_evsel *evsel)
+{
+   u64 read_format = evsel->attr.read_format;
+   PyObject *values;
+   unsigned int i;
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+   pydict_set_item_string_decref(dict_sample, "time_enabled",
+   PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+   }
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+   pydict_set_item_string_decref(dict_sample, "time_running",
+   PyLong_FromUnsignedLongLong(sample->read.time_running));
+   }
+
+   if (read_format & PERF_FORMAT_GROUP)
+   values = PyList_New(sample->read.group.nr);
+   else
+   values = PyList_New(1);
+
+   if (!values)
+   Py_FatalError("couldn't create Python list");
+
+   if (read_format & PERF_FORMAT_GROUP) {
+   for (i = 0; i < sample->read.group.nr; i++) {
+   PyObject *t = 
get_sample_value_as_tuple(>read.group.values[i]);
+   PyList_SET_ITEM(values, i, t);
+   }
+   } else {
+   PyObject *t = get_sample_value_as_tuple(>read.one);
+   PyList_SET_ITEM(values, 0, t);
+   }
+   pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
 static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 struct perf_evsel *evsel,
 struct addr_location *al,
@@ -422,6 +472,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample 
*sample,
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
PyLong_FromUnsignedLongLong(sample->period));
+   set_sample_read_in_dict(dict_sample, sample, evsel);
pydict_set_item_string_decref(dict, "sample", dict_sample);
 
pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(


[tip:perf/core] perf script python: Refactor creation of perf sample dict

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  892e76b2e8c5e85e69514478e3319575a68b9770
Gitweb: http://git.kernel.org/tip/892e76b2e8c5e85e69514478e3319575a68b9770
Author: Arun Kalyanasundaram <arunk...@google.com>
AuthorDate: Fri, 21 Jul 2017 15:04:19 -0700
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Tue, 25 Jul 2017 22:43:19 -0300

perf script python: Refactor creation of perf sample dict

Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Carrillo-Cisneros <davi...@google.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Seongjae Park <sj38.p...@gmail.com>
Cc: Stephane Eranian <eran...@google.com>
Link: http://lkml.kernel.org/r/20170721220422.63962-3-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f482..69d1b6d 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ exit:
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   

[tip:perf/core] perf script python: Refactor creation of perf sample dict

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  892e76b2e8c5e85e69514478e3319575a68b9770
Gitweb: http://git.kernel.org/tip/892e76b2e8c5e85e69514478e3319575a68b9770
Author: Arun Kalyanasundaram 
AuthorDate: Fri, 21 Jul 2017 15:04:19 -0700
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 25 Jul 2017 22:43:19 -0300

perf script python: Refactor creation of perf sample dict

Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram 
Acked-by: Jiri Olsa 
Cc: Alexander Shishkin 
Cc: Daniel Borkmann 
Cc: David Carrillo-Cisneros 
Cc: David S. Miller 
Cc: Peter Zijlstra 
Cc: Seongjae Park 
Cc: Stephane Eranian 
Link: http://lkml.kernel.org/r/20170721220422.63962-3-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f482..69d1b6d 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ exit:
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   

[tip:perf/core] perf script python: Allocate memory only if handler exists

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  e9f9a9ca8588e58dc0800b44adc41d32f6fc813a
Gitweb: http://git.kernel.org/tip/e9f9a9ca8588e58dc0800b44adc41d32f6fc813a
Author: Arun Kalyanasundaram <arunk...@google.com>
AuthorDate: Fri, 21 Jul 2017 15:04:18 -0700
Committer:  Arnaldo Carvalho de Melo <a...@redhat.com>
CommitDate: Tue, 25 Jul 2017 22:43:18 -0300

perf script python: Allocate memory only if handler exists

Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
Acked-by: Jiri Olsa <jo...@kernel.org>
Cc: Alexander Shishkin <alexander.shish...@linux.intel.com>
Cc: Daniel Borkmann <dan...@iogearbox.net>
Cc: David Carrillo-Cisneros <davi...@google.com>
Cc: David S. Miller <da...@davemloft.net>
Cc: Peter Zijlstra <pet...@infradead.org>
Cc: Seongjae Park <sj38.p...@gmail.com>
Cc: Stephane Eranian <eran...@google.com>
Link: http://lkml.kernel.org/r/20170721220422.63962-2-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo <a...@redhat.com>
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00..8a8f482 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't creat

[tip:perf/core] perf script python: Allocate memory only if handler exists

2017-07-26 Thread tip-bot for Arun Kalyanasundaram
Commit-ID:  e9f9a9ca8588e58dc0800b44adc41d32f6fc813a
Gitweb: http://git.kernel.org/tip/e9f9a9ca8588e58dc0800b44adc41d32f6fc813a
Author: Arun Kalyanasundaram 
AuthorDate: Fri, 21 Jul 2017 15:04:18 -0700
Committer:  Arnaldo Carvalho de Melo 
CommitDate: Tue, 25 Jul 2017 22:43:18 -0300

perf script python: Allocate memory only if handler exists

Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram 
Acked-by: Jiri Olsa 
Cc: Alexander Shishkin 
Cc: Daniel Borkmann 
Cc: David Carrillo-Cisneros 
Cc: David S. Miller 
Cc: Peter Zijlstra 
Cc: Seongjae Park 
Cc: Stephane Eranian 
Link: http://lkml.kernel.org/r/20170721220422.63962-2-arunk...@google.com
Signed-off-by: Arnaldo Carvalho de Melo 
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00..8a8f482 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
 

[PATCH v2 2/5] perf script python: Refactor creation of perf sample dict

2017-07-21 Thread Arun Kalyanasundaram
Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f4829d3e2..69d1b6db96f6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
-   (const char *)>attr, sizeof(evsel->attr)));
-
-   pydict_set_item_string_decref(dict_sample, "pid",
-   PyInt_FromLong(sample->pid));
-   pydict_set_item_string_decref(dict_sample, "tid",
-   PyInt_FromLong(sample->tid));
-   pydict_set_item_string_decref(dict_sample, "cpu",
-   PyInt_FromLong(sample->

[PATCH v2 2/5] perf script python: Refactor creation of perf sample dict

2017-07-21 Thread Arun Kalyanasundaram
Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f4829d3e2..69d1b6db96f6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
-   (const char *)>attr, sizeof(evsel->attr)));
-
-   pydict_set_item_string_decref(dict_sample, "pid",
-   PyInt_FromLong(sample->pid));
-   pydict_set_item_string_decref(dict_sample, "tid",
-   PyInt_FromLong(sample->tid));
-   pydict_set_item_string_decref(dict_sample, "cpu",
-   PyInt_FromLong(sample->cpu));
-   pydict_set_item_string_decref(dict_sample, &q

[PATCH v2 1/5] perf script python: Allocate memory only if handler exists

2017-07-21 Thread Arun Kalyanasundaram
Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..8a8f4829d3e2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)>attr, sizeof(evsel->attr)));
@@ -861,7 +867,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
Py_FatalError("error resizing Python tuple");
 
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
 }
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 1/5] perf script python: Allocate memory only if handler exists

2017-07-21 Thread Arun Kalyanasundaram
Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..8a8f4829d3e2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)>attr, sizeof(evsel->attr)));
@@ -861,7 +867,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
Py_FatalError("error resizing Python tuple");
 
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
 }
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 4/5] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-21 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
Changes in v2:
- Make an explicit call to Py_INCREF on callchain in process
  tracepoint to keep the object alive in get_perf_sample_dict.

 .../util/scripting-engines/trace-event-python.c| 41 +-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a45784c910..938b39f6ad31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+   /* Need an additional reference for the perf_sample dict */
+   Py_INCREF(callchain);
 
if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   } else {
+   Py_DECREF(callchain);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 4/5] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-21 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram 
---
Changes in v2:
- Make an explicit call to Py_INCREF on callchain in process
  tracepoint to keep the object alive in get_perf_sample_dict.

 .../util/scripting-engines/trace-event-python.c| 41 +-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a45784c910..938b39f6ad31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+   /* Need an additional reference for the perf_sample dict */
+   Py_INCREF(callchain);
 
if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   } else {
+   Py_DECREF(callchain);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 3/5] perf script python: Add sample_read to dict

2017-07-21 Thread Arun Kalyanasundaram
Provide time_enabled, time_running and counter value in the perf_sample
dict.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 51 ++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6db96f6..55a45784c910 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,56 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+   PyObject *t;
+
+   t = PyTuple_New(2);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+   PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+   PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+   return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+struct perf_sample *sample,
+struct perf_evsel *evsel)
+{
+   u64 read_format = evsel->attr.read_format;
+   PyObject *values;
+   unsigned int i;
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+   pydict_set_item_string_decref(dict_sample, "time_enabled",
+   PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+   }
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+   pydict_set_item_string_decref(dict_sample, "time_running",
+   PyLong_FromUnsignedLongLong(sample->read.time_running));
+   }
+
+   if (read_format & PERF_FORMAT_GROUP)
+   values = PyList_New(sample->read.group.nr);
+   else
+   values = PyList_New(1);
+
+   if (!values)
+   Py_FatalError("couldn't create Python list");
+
+   if (read_format & PERF_FORMAT_GROUP) {
+   for (i = 0; i < sample->read.group.nr; i++) {
+   PyObject *t = 
get_sample_value_as_tuple(>read.group.values[i]);
+   PyList_SET_ITEM(values, i, t);
+   }
+   } else {
+   PyObject *t = get_sample_value_as_tuple(>read.one);
+   PyList_SET_ITEM(values, 0, t);
+   }
+   pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
 static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 struct perf_evsel *evsel,
 struct addr_location *al,
@@ -422,6 +472,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample 
*sample,
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
PyLong_FromUnsignedLongLong(sample->period));
+   set_sample_read_in_dict(dict_sample, sample, evsel);
pydict_set_item_string_decref(dict, "sample", dict_sample);
 
pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 3/5] perf script python: Add sample_read to dict

2017-07-21 Thread Arun Kalyanasundaram
Provide time_enabled, time_running and counter value in the perf_sample
dict.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 51 ++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6db96f6..55a45784c910 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,56 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+   PyObject *t;
+
+   t = PyTuple_New(2);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+   PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+   PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+   return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+struct perf_sample *sample,
+struct perf_evsel *evsel)
+{
+   u64 read_format = evsel->attr.read_format;
+   PyObject *values;
+   unsigned int i;
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+   pydict_set_item_string_decref(dict_sample, "time_enabled",
+   PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+   }
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+   pydict_set_item_string_decref(dict_sample, "time_running",
+   PyLong_FromUnsignedLongLong(sample->read.time_running));
+   }
+
+   if (read_format & PERF_FORMAT_GROUP)
+   values = PyList_New(sample->read.group.nr);
+   else
+   values = PyList_New(1);
+
+   if (!values)
+   Py_FatalError("couldn't create Python list");
+
+   if (read_format & PERF_FORMAT_GROUP) {
+   for (i = 0; i < sample->read.group.nr; i++) {
+   PyObject *t = 
get_sample_value_as_tuple(>read.group.values[i]);
+   PyList_SET_ITEM(values, i, t);
+   }
+   } else {
+   PyObject *t = get_sample_value_as_tuple(>read.one);
+   PyList_SET_ITEM(values, 0, t);
+   }
+   pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
 static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 struct perf_evsel *evsel,
 struct addr_location *al,
@@ -422,6 +472,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample 
*sample,
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
PyLong_FromUnsignedLongLong(sample->period));
+   set_sample_read_in_dict(dict_sample, sample, evsel);
pydict_set_item_string_decref(dict, "sample", dict_sample);
 
pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 5/5] perf script python: Generate hooks with additional argument

2017-07-21 Thread Arun Kalyanasundaram
Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 938b39f6ad31..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1367,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1436,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1446,15 +1455,20 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
-   "(event_name, cpu, secs, nsecs, pid, comm),\n");
+   "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
 
fclose(ofp);
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 0/5] perf script python: Provide sample dict to all handlers

2017-07-21 Thread Arun Kalyanasundaram
v2: - Add sample_read struct to the dict (in 3/5).
- Increase reference count of callchain in process tracepoint to
  avoid unnecessary garbage collection (in 4/5).

The process_event python hook receives a dict with most perf_sample entries.

Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate the 
introduction of this dict and do not receive it. This patch series adds the 
dict to all handlers, aiming to unify the information passed to them.

This change adds an additional argument to the affected handlers. To keep 
backwards compatibility (and avoid unnecessary work), do not pass the 
aforementioned dict if the number of arguments signals that handler version 
predates this change.

In addition, provide time_enabled, time_running and counter value in the 
perf_sample dict.

Initial Discussion: https://lkml.org/lkml/2017/7/1/108

Arun Kalyanasundaram (5):
  perf script python: Allocate memory only if handler exists
  perf script python: Refactor creation of perf sample dict
  perf script python: Add sample_read to dict
  perf script python: Add perf_sample dict to tracepoint handlers
  perf script python: Generate hooks with additional argument

 .../util/scripting-engines/trace-event-python.c| 246 +++--
 1 file changed, 184 insertions(+), 62 deletions(-)

-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 5/5] perf script python: Generate hooks with additional argument

2017-07-21 Thread Arun Kalyanasundaram
Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 938b39f6ad31..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1367,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1436,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1446,15 +1455,20 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
-   "(event_name, cpu, secs, nsecs, pid, comm),\n");
+   "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
 
fclose(ofp);
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH v2 0/5] perf script python: Provide sample dict to all handlers

2017-07-21 Thread Arun Kalyanasundaram
v2: - Add sample_read struct to the dict (in 3/5).
- Increase reference count of callchain in process tracepoint to
  avoid unnecessary garbage collection (in 4/5).

The process_event python hook receives a dict with most perf_sample entries.

Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate the 
introduction of this dict and do not receive it. This patch series adds the 
dict to all handlers, aiming to unify the information passed to them.

This change adds an additional argument to the affected handlers. To keep 
backwards compatibility (and avoid unnecessary work), do not pass the 
aforementioned dict if the number of arguments signals that handler version 
predates this change.

In addition, provide time_enabled, time_running and counter value in the 
perf_sample dict.

Initial Discussion: https://lkml.org/lkml/2017/7/1/108

Arun Kalyanasundaram (5):
  perf script python: Allocate memory only if handler exists
  perf script python: Refactor creation of perf sample dict
  perf script python: Add sample_read to dict
  perf script python: Add perf_sample dict to tracepoint handlers
  perf script python: Generate hooks with additional argument

 .../util/scripting-engines/trace-event-python.c| 246 +++--
 1 file changed, 184 insertions(+), 62 deletions(-)

-- 
2.14.0.rc0.284.gd933b75aa4-goog



Re: [PATCH 0/5] perf script python: Provide perf_sample dict to all handlers

2017-07-21 Thread Arun Kalyanasundaram
My apologies. Yes, I did make a couple of changes to the patch. I was
not sure if I should be sending a v2 since the previous one was a rfc.
Please ignore this patch, I will resend this highlighting the new
changes made.

On Fri, Jul 21, 2017 at 9:28 AM, Arnaldo Carvalho de Melo
<a...@kernel.org> wrote:
> Em Fri, Jul 21, 2017 at 09:46:39AM +0200, Jiri Olsa escreveu:
>> On Thu, Jul 20, 2017 at 07:01:13PM -0700, Arun Kalyanasundaram wrote:
>> > The process_event python hook receives a dict with most perf_sample
>> > entries.
>>
>> hi,
>> was there any change to the rfc post?
>
> I was wondering that, please stick a v1, v2, etc to the subject, and
> state the changes across versions, to make things clear.
>
> - Arnaldo
>
>> thanks,
>> jirka
>>
>> >
>> > Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate
>> > the introduction of this dict and do not receive it. This patch series
>> > adds the dict to all handlers, aiming to unify the information passed to
>> > them.
>> >
>> > This change adds an additional argument to the affected handlers. To
>> > keep backwards compatibility (and avoid unnecessary work), do not pass
>> > the aforementioned dict if the number of arguments signals that handler
>> > version predates this change.
>> >
>> > In addition, provide time_enabled, time_running and counter value in the
>> > perf_sample dict.
>> >
>> > Initial Discussion: https://lkml.org/lkml/2017/7/1/108
>> >
>> > Arun Kalyanasundaram (5):
>> >   perf script python: Allocate memory only if handler exists
>> >   perf script python: Refactor creation of perf sample dict
>> >   perf script python: Add sample_read to dict
>> >   perf script python: Add perf_sample dict to tracepoint handlers
>> >   perf script python: Generate hooks with additional argument
>> >
>> >  .../util/scripting-engines/trace-event-python.c| 246 
>> > +++--
>> >  1 file changed, 184 insertions(+), 62 deletions(-)
>> >
>> > --
>> > 2.14.0.rc0.284.gd933b75aa4-goog
>> >


Re: [PATCH 0/5] perf script python: Provide perf_sample dict to all handlers

2017-07-21 Thread Arun Kalyanasundaram
My apologies. Yes, I did make a couple of changes to the patch. I was
not sure if I should be sending a v2 since the previous one was a rfc.
Please ignore this patch, I will resend this highlighting the new
changes made.

On Fri, Jul 21, 2017 at 9:28 AM, Arnaldo Carvalho de Melo
 wrote:
> Em Fri, Jul 21, 2017 at 09:46:39AM +0200, Jiri Olsa escreveu:
>> On Thu, Jul 20, 2017 at 07:01:13PM -0700, Arun Kalyanasundaram wrote:
>> > The process_event python hook receives a dict with most perf_sample
>> > entries.
>>
>> hi,
>> was there any change to the rfc post?
>
> I was wondering that, please stick a v1, v2, etc to the subject, and
> state the changes across versions, to make things clear.
>
> - Arnaldo
>
>> thanks,
>> jirka
>>
>> >
>> > Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate
>> > the introduction of this dict and do not receive it. This patch series
>> > adds the dict to all handlers, aiming to unify the information passed to
>> > them.
>> >
>> > This change adds an additional argument to the affected handlers. To
>> > keep backwards compatibility (and avoid unnecessary work), do not pass
>> > the aforementioned dict if the number of arguments signals that handler
>> > version predates this change.
>> >
>> > In addition, provide time_enabled, time_running and counter value in the
>> > perf_sample dict.
>> >
>> > Initial Discussion: https://lkml.org/lkml/2017/7/1/108
>> >
>> > Arun Kalyanasundaram (5):
>> >   perf script python: Allocate memory only if handler exists
>> >   perf script python: Refactor creation of perf sample dict
>> >   perf script python: Add sample_read to dict
>> >   perf script python: Add perf_sample dict to tracepoint handlers
>> >   perf script python: Generate hooks with additional argument
>> >
>> >  .../util/scripting-engines/trace-event-python.c| 246 
>> > +++--
>> >  1 file changed, 184 insertions(+), 62 deletions(-)
>> >
>> > --
>> > 2.14.0.rc0.284.gd933b75aa4-goog
>> >


[PATCH 1/5] perf script python: Allocate memory only if handler exists

2017-07-20 Thread Arun Kalyanasundaram
Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..8a8f4829d3e2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)>attr, sizeof(evsel->attr)));
@@ -861,7 +867,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
Py_FatalError("error resizing Python tuple");
 
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
 }
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 2/5] perf script python: Refactor creation of perf sample dict

2017-07-20 Thread Arun Kalyanasundaram
Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f4829d3e2..69d1b6db96f6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
-   (const char *)>attr, sizeof(evsel->attr)));
-
-   pydict_set_item_string_decref(dict_sample, "pid",
-   PyInt_FromLong(sample->pid));
-   pydict_set_item_string_decref(dict_sample, "tid",
-   PyInt_FromLong(sample->tid));
-   pydict_set_item_string_decref(dict_sample, "cpu",
-   PyInt_FromLong(sample->

[PATCH 1/5] perf script python: Allocate memory only if handler exists

2017-07-20 Thread Arun Kalyanasundaram
Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..8a8f4829d3e2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)>attr, sizeof(evsel->attr)));
@@ -861,7 +867,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
Py_FatalError("error resizing Python tuple");
 
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
 }
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 2/5] perf script python: Refactor creation of perf sample dict

2017-07-20 Thread Arun Kalyanasundaram
Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f4829d3e2..69d1b6db96f6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
-   (const char *)>attr, sizeof(evsel->attr)));
-
-   pydict_set_item_string_decref(dict_sample, "pid",
-   PyInt_FromLong(sample->pid));
-   pydict_set_item_string_decref(dict_sample, "tid",
-   PyInt_FromLong(sample->tid));
-   pydict_set_item_string_decref(dict_sample, "cpu",
-   PyInt_FromLong(sample->cpu));
-   pydict_set_item_string_decref(dict_sample, &q

[PATCH 4/5] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-20 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 41 +-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a45784c910..938b39f6ad31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+   /* Need an additional reference for the perf_sample dict */
+   Py_INCREF(callchain);
 
if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   } else {
+   Py_DECREF(callchain);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 4/5] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-20 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 41 +-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 55a45784c910..938b39f6ad31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -499,7 +527,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -552,6 +580,8 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
+   /* Need an additional reference for the perf_sample dict */
+   Py_INCREF(callchain);
 
if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
@@ -602,6 +632,14 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   } else {
+   Py_DECREF(callchain);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -612,6 +650,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 5/5] perf script python: Generate hooks with additional argument

2017-07-20 Thread Arun Kalyanasundaram
Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 938b39f6ad31..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1367,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1436,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1446,15 +1455,20 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
-   "(event_name, cpu, secs, nsecs, pid, comm),\n");
+   "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
 
fclose(ofp);
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 5/5] perf script python: Generate hooks with additional argument

2017-07-20 Thread Arun Kalyanasundaram
Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 22 ++
 1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 938b39f6ad31..c7187f067d31 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1367,6 +1367,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1436,6 +1442,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1446,15 +1455,20 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
-   "(event_name, cpu, secs, nsecs, pid, comm),\n");
+   "(event_name, cpu, secs, nsecs, pid, comm),\n\n");
+
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])\n");
 
fclose(ofp);
 
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 0/5] perf script python: Provide perf_sample dict to all handlers

2017-07-20 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with most perf_sample
entries.

Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate
the introduction of this dict and do not receive it. This patch series
adds the dict to all handlers, aiming to unify the information passed to
them.

This change adds an additional argument to the affected handlers. To
keep backwards compatibility (and avoid unnecessary work), do not pass
the aforementioned dict if the number of arguments signals that handler
version predates this change.

In addition, provide time_enabled, time_running and counter value in the
perf_sample dict.

Initial Discussion: https://lkml.org/lkml/2017/7/1/108

Arun Kalyanasundaram (5):
  perf script python: Allocate memory only if handler exists
  perf script python: Refactor creation of perf sample dict
  perf script python: Add sample_read to dict
  perf script python: Add perf_sample dict to tracepoint handlers
  perf script python: Generate hooks with additional argument

 .../util/scripting-engines/trace-event-python.c| 246 +++--
 1 file changed, 184 insertions(+), 62 deletions(-)

-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 3/5] perf script python: Add sample_read to dict

2017-07-20 Thread Arun Kalyanasundaram
Provide time_enabled, time_running and counter value in the perf_sample
dict.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 51 ++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6db96f6..55a45784c910 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,56 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+   PyObject *t;
+
+   t = PyTuple_New(2);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+   PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+   PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+   return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+struct perf_sample *sample,
+struct perf_evsel *evsel)
+{
+   u64 read_format = evsel->attr.read_format;
+   PyObject *values;
+   unsigned int i;
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+   pydict_set_item_string_decref(dict_sample, "time_enabled",
+   PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+   }
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+   pydict_set_item_string_decref(dict_sample, "time_running",
+   PyLong_FromUnsignedLongLong(sample->read.time_running));
+   }
+
+   if (read_format & PERF_FORMAT_GROUP)
+   values = PyList_New(sample->read.group.nr);
+   else
+   values = PyList_New(1);
+
+   if (!values)
+   Py_FatalError("couldn't create Python list");
+
+   if (read_format & PERF_FORMAT_GROUP) {
+   for (i = 0; i < sample->read.group.nr; i++) {
+   PyObject *t = 
get_sample_value_as_tuple(>read.group.values[i]);
+   PyList_SET_ITEM(values, i, t);
+   }
+   } else {
+   PyObject *t = get_sample_value_as_tuple(>read.one);
+   PyList_SET_ITEM(values, 0, t);
+   }
+   pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
 static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 struct perf_evsel *evsel,
 struct addr_location *al,
@@ -422,6 +472,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample 
*sample,
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
PyLong_FromUnsignedLongLong(sample->period));
+   set_sample_read_in_dict(dict_sample, sample, evsel);
pydict_set_item_string_decref(dict, "sample", dict_sample);
 
pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 0/5] perf script python: Provide perf_sample dict to all handlers

2017-07-20 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with most perf_sample
entries.

Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate
the introduction of this dict and do not receive it. This patch series
adds the dict to all handlers, aiming to unify the information passed to
them.

This change adds an additional argument to the affected handlers. To
keep backwards compatibility (and avoid unnecessary work), do not pass
the aforementioned dict if the number of arguments signals that handler
version predates this change.

In addition, provide time_enabled, time_running and counter value in the
perf_sample dict.

Initial Discussion: https://lkml.org/lkml/2017/7/1/108

Arun Kalyanasundaram (5):
  perf script python: Allocate memory only if handler exists
  perf script python: Refactor creation of perf sample dict
  perf script python: Add sample_read to dict
  perf script python: Add perf_sample dict to tracepoint handlers
  perf script python: Generate hooks with additional argument

 .../util/scripting-engines/trace-event-python.c| 246 +++--
 1 file changed, 184 insertions(+), 62 deletions(-)

-- 
2.14.0.rc0.284.gd933b75aa4-goog



[PATCH 3/5] perf script python: Add sample_read to dict

2017-07-20 Thread Arun Kalyanasundaram
Provide time_enabled, time_running and counter value in the perf_sample
dict.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 51 ++
 1 file changed, 51 insertions(+)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6db96f6..55a45784c910 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,56 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_sample_value_as_tuple(struct sample_read_value *value)
+{
+   PyObject *t;
+
+   t = PyTuple_New(2);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+   PyTuple_SetItem(t, 0, PyLong_FromUnsignedLongLong(value->id));
+   PyTuple_SetItem(t, 1, PyLong_FromUnsignedLongLong(value->value));
+   return t;
+}
+
+static void set_sample_read_in_dict(PyObject *dict_sample,
+struct perf_sample *sample,
+struct perf_evsel *evsel)
+{
+   u64 read_format = evsel->attr.read_format;
+   PyObject *values;
+   unsigned int i;
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_ENABLED) {
+   pydict_set_item_string_decref(dict_sample, "time_enabled",
+   PyLong_FromUnsignedLongLong(sample->read.time_enabled));
+   }
+
+   if (read_format & PERF_FORMAT_TOTAL_TIME_RUNNING) {
+   pydict_set_item_string_decref(dict_sample, "time_running",
+   PyLong_FromUnsignedLongLong(sample->read.time_running));
+   }
+
+   if (read_format & PERF_FORMAT_GROUP)
+   values = PyList_New(sample->read.group.nr);
+   else
+   values = PyList_New(1);
+
+   if (!values)
+   Py_FatalError("couldn't create Python list");
+
+   if (read_format & PERF_FORMAT_GROUP) {
+   for (i = 0; i < sample->read.group.nr; i++) {
+   PyObject *t = 
get_sample_value_as_tuple(>read.group.values[i]);
+   PyList_SET_ITEM(values, i, t);
+   }
+   } else {
+   PyObject *t = get_sample_value_as_tuple(>read.one);
+   PyList_SET_ITEM(values, 0, t);
+   }
+   pydict_set_item_string_decref(dict_sample, "values", values);
+}
+
 static PyObject *get_perf_sample_dict(struct perf_sample *sample,
 struct perf_evsel *evsel,
 struct addr_location *al,
@@ -422,6 +472,7 @@ static PyObject *get_perf_sample_dict(struct perf_sample 
*sample,
PyLong_FromUnsignedLongLong(sample->time));
pydict_set_item_string_decref(dict_sample, "period",
PyLong_FromUnsignedLongLong(sample->period));
+   set_sample_read_in_dict(dict_sample, sample, evsel);
pydict_set_item_string_decref(dict, "sample", dict_sample);
 
pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
-- 
2.14.0.rc0.284.gd933b75aa4-goog



Re: [RFC 0/4] perf script python: Provide perf_sample dict to all handlers

2017-07-18 Thread Arun Kalyanasundaram
Thank you for taking a look into it. I don't see the garbled output.
Can you please send me the  perf.data file or a way to reproduce it?

On Tue, Jul 18, 2017 at 1:35 AM, Jiri Olsa <jo...@redhat.com> wrote:
> On Mon, Jul 17, 2017 at 03:10:36PM -0700, Arun Kalyanasundaram wrote:
>> The process_event python hook receives a dict with all perf_sample entries.
>>
>> Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate the 
>> introduction of this dict and do not receive it. This patch series adds the 
>> dict to all handlers, aiming to unify the information passed to them.
>>
>> This change adds an additional argument to the affected handlers. To keep 
>> backwards compatibility (and avoid unnecessary work), do not pass the 
>> aforementioned dict if the number of arguments signals that handler version 
>> predates this change.
>>
>> Initial Discussion: https://lkml.org/lkml/2017/7/1/108
>>
>> Arun Kalyanasundaram (4):
>>   perf script python: Allocate memory only if handler exists
>>   perf script python: Refactor creation of perf sample dict
>>   perf script python: Add perf_sample dict to tracepoint handlers
>>   perf script python: Generate hooks with additional argument
>>
>>  .../util/scripting-engines/trace-event-python.c| 189 
>> ++---
>>  1 file changed, 128 insertions(+), 61 deletions(-)
>
> looks good, but any idea the perf-script.py output gives
> some trash at the end of 'comm' args? like:
>
> sched__sched_stat_runtime 1 199971.01018286921999 perf
>   comm=perf^@^@-x86_64-l^@, pid=21999
>
>
> thanks,
> jirka


Re: [RFC 0/4] perf script python: Provide perf_sample dict to all handlers

2017-07-18 Thread Arun Kalyanasundaram
Thank you for taking a look into it. I don't see the garbled output.
Can you please send me the  perf.data file or a way to reproduce it?

On Tue, Jul 18, 2017 at 1:35 AM, Jiri Olsa  wrote:
> On Mon, Jul 17, 2017 at 03:10:36PM -0700, Arun Kalyanasundaram wrote:
>> The process_event python hook receives a dict with all perf_sample entries.
>>
>> Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate the 
>> introduction of this dict and do not receive it. This patch series adds the 
>> dict to all handlers, aiming to unify the information passed to them.
>>
>> This change adds an additional argument to the affected handlers. To keep 
>> backwards compatibility (and avoid unnecessary work), do not pass the 
>> aforementioned dict if the number of arguments signals that handler version 
>> predates this change.
>>
>> Initial Discussion: https://lkml.org/lkml/2017/7/1/108
>>
>> Arun Kalyanasundaram (4):
>>   perf script python: Allocate memory only if handler exists
>>   perf script python: Refactor creation of perf sample dict
>>   perf script python: Add perf_sample dict to tracepoint handlers
>>   perf script python: Generate hooks with additional argument
>>
>>  .../util/scripting-engines/trace-event-python.c| 189 
>> ++---
>>  1 file changed, 128 insertions(+), 61 deletions(-)
>
> looks good, but any idea the perf-script.py output gives
> some trash at the end of 'comm' args? like:
>
> sched__sched_stat_runtime 1 199971.01018286921999 perf
>   comm=perf^@^@-x86_64-l^@, pid=21999
>
>
> thanks,
> jirka


[RFC 2/4] perf script python: Refactor creation of perf sample dict

2017-07-17 Thread Arun Kalyanasundaram
Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f4829d3e2..69d1b6db96f6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
-   (const char *)>attr, sizeof(evsel->attr)));
-
-   pydict_set_item_string_decref(dict_sample, "pid",
-   PyInt_FromLong(sample->pid));
-   pydict_set_item_string_decref(dict_sample, "tid",
-   PyInt_FromLong(sample->tid));
-   pydict_set_item_string_decref(dict_sample, "cpu",
-   PyInt_FromLong(sample->

[RFC 2/4] perf script python: Refactor creation of perf sample dict

2017-07-17 Thread Arun Kalyanasundaram
Move the creation of the dict containing perf_sample entries into a
helper function to enable its reuse in other sample processing routines.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 94 --
 1 file changed, 53 insertions(+), 41 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 8a8f4829d3e2..69d1b6db96f6 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -391,6 +391,57 @@ static PyObject *python_process_callchain(struct 
perf_sample *sample,
return pylist;
 }
 
+static PyObject *get_perf_sample_dict(struct perf_sample *sample,
+struct perf_evsel *evsel,
+struct addr_location *al,
+PyObject *callchain)
+{
+   PyObject *dict, *dict_sample;
+
+   dict = PyDict_New();
+   if (!dict)
+   Py_FatalError("couldn't create Python dictionary");
+
+   dict_sample = PyDict_New();
+   if (!dict_sample)
+   Py_FatalError("couldn't create Python dictionary");
+
+   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
+   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
+   (const char *)>attr, sizeof(evsel->attr)));
+
+   pydict_set_item_string_decref(dict_sample, "pid",
+   PyInt_FromLong(sample->pid));
+   pydict_set_item_string_decref(dict_sample, "tid",
+   PyInt_FromLong(sample->tid));
+   pydict_set_item_string_decref(dict_sample, "cpu",
+   PyInt_FromLong(sample->cpu));
+   pydict_set_item_string_decref(dict_sample, "ip",
+   PyLong_FromUnsignedLongLong(sample->ip));
+   pydict_set_item_string_decref(dict_sample, "time",
+   PyLong_FromUnsignedLongLong(sample->time));
+   pydict_set_item_string_decref(dict_sample, "period",
+   PyLong_FromUnsignedLongLong(sample->period));
+   pydict_set_item_string_decref(dict, "sample", dict_sample);
+
+   pydict_set_item_string_decref(dict, "raw_buf", 
PyString_FromStringAndSize(
+   (const char *)sample->raw_data, sample->raw_size));
+   pydict_set_item_string_decref(dict, "comm",
+   PyString_FromString(thread__comm_str(al->thread)));
+   if (al->map) {
+   pydict_set_item_string_decref(dict, "dso",
+   PyString_FromString(al->map->dso->name));
+   }
+   if (al->sym) {
+   pydict_set_item_string_decref(dict, "symbol",
+   PyString_FromString(al->sym->name));
+   }
+
+   pydict_set_item_string_decref(dict, "callchain", callchain);
+
+   return dict;
+}
+
 static void python_process_tracepoint(struct perf_sample *sample,
  struct perf_evsel *evsel,
  struct addr_location *al)
@@ -801,7 +852,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
 struct perf_evsel *evsel,
 struct addr_location *al)
 {
-   PyObject *handler, *t, *dict, *callchain, *dict_sample;
+   PyObject *handler, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
 
@@ -819,48 +870,9 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!t)
Py_FatalError("couldn't create Python tuple");
 
-   dict = PyDict_New();
-   if (!dict)
-   Py_FatalError("couldn't create Python dictionary");
-
-   dict_sample = PyDict_New();
-   if (!dict_sample)
-   Py_FatalError("couldn't create Python dictionary");
-
-   pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
-   pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
-   (const char *)>attr, sizeof(evsel->attr)));
-
-   pydict_set_item_string_decref(dict_sample, "pid",
-   PyInt_FromLong(sample->pid));
-   pydict_set_item_string_decref(dict_sample, "tid",
-   PyInt_FromLong(sample->tid));
-   pydict_set_item_string_decref(dict_sample, "cpu",
-   PyInt_FromLong(sample->cpu));
-   pydict_set_item_string_decref(dict_sample, &q

[RFC 3/4] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-17 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 37 +-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6db96f6..a23f5940f826 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -448,7 +476,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -551,6 +579,12 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -561,6 +595,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 
-- 
2.13.2.932.g7449e964c-goog



[RFC 3/4] perf script python: Add perf_sample dict to tracepoint handlers

2017-07-17 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample
entries, but the tracepoint specific and trace_unhandled hooks predate
the introduction of this dict, and do not receive it.

Add the aforementioned dict as an additional argument to the affected
handlers. To keep backwards compatibility (and avoid unnecessary work),
do not pass the dict if the number of arguments signals that handler
version predates this change.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 37 +-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 69d1b6db96f6..a23f5940f826 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -116,6 +116,34 @@ static PyObject *get_handler(const char *handler_name)
return handler;
 }
 
+static int get_argument_count(PyObject *handler)
+{
+   int arg_count = 0;
+
+   /*
+* The attribute for the code object is func_code in Python 2,
+* whereas it is __code__ in Python 3.0+.
+*/
+   PyObject *code_obj = PyObject_GetAttrString(handler,
+   "func_code");
+   if (PyErr_Occurred()) {
+   PyErr_Clear();
+   code_obj = PyObject_GetAttrString(handler,
+   "__code__");
+   }
+   PyErr_Clear();
+   if (code_obj) {
+   PyObject *arg_count_obj = PyObject_GetAttrString(code_obj,
+   "co_argcount");
+   if (arg_count_obj) {
+   arg_count = (int) PyInt_AsLong(arg_count_obj);
+   Py_DECREF(arg_count_obj);
+   }
+   Py_DECREF(code_obj);
+   }
+   return arg_count;
+}
+
 static void call_object(PyObject *handler, PyObject *args, const char *die_msg)
 {
PyObject *retval;
@@ -448,7 +476,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 {
struct event_format *event = evsel->tp_format;
PyObject *handler, *context, *t, *obj = NULL, *callchain;
-   PyObject *dict = NULL;
+   PyObject *dict = NULL, *all_entries_dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@@ -551,6 +579,12 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
if (dict)
PyTuple_SetItem(t, n++, dict);
 
+   if (get_argument_count(handler) == (int) n + 1) {
+   all_entries_dict = get_perf_sample_dict(sample, evsel, al,
+   callchain);
+   PyTuple_SetItem(t, n++, all_entries_dict);
+   }
+
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
@@ -561,6 +595,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
Py_DECREF(dict);
}
 
+   Py_XDECREF(all_entries_dict);
Py_DECREF(t);
 }
 
-- 
2.13.2.932.g7449e964c-goog



[RFC 1/4] perf script python: Allocate memory only if handler exists

2017-07-17 Thread Arun Kalyanasundaram
Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..8a8f4829d3e2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)>attr, sizeof(evsel->attr)));
@@ -861,7 +867,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
Py_FatalError("error resizing Python tuple");
 
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
 }
-- 
2.13.2.932.g7449e964c-goog



[RFC 1/4] perf script python: Allocate memory only if handler exists

2017-07-17 Thread Arun Kalyanasundaram
Avoid allocating memory if hook handler is not available. This saves
unused memory allocation and simplifies error path.

Let handler in python_process_tracepoint point to either tracepoint
specific or trace_unhandled hook. Use dict to check if handler points to
trace_unhandled.

Remove the exit label in python_process_general_event and return when no
handler is available.

Signed-off-by: Arun Kalyanasundaram 
---
 .../util/scripting-engines/trace-event-python.c| 38 +-
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index 57b7a00e6f16..8a8f4829d3e2 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -407,10 +407,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
void *data = sample->raw_data;
unsigned long long nsecs = sample->time;
const char *comm = thread__comm_str(al->thread);
-
-   t = PyTuple_New(MAX_FIELDS);
-   if (!t)
-   Py_FatalError("couldn't create Python tuple");
+   const char *default_handler_name = "trace_unhandled";
 
if (!event) {
snprintf(handler_name, sizeof(handler_name),
@@ -427,10 +424,19 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
 
handler = get_handler(handler_name);
if (!handler) {
+   handler = get_handler(default_handler_name);
+   if (!handler)
+   return;
dict = PyDict_New();
if (!dict)
Py_FatalError("couldn't create Python dict");
}
+
+   t = PyTuple_New(MAX_FIELDS);
+   if (!t)
+   Py_FatalError("couldn't create Python tuple");
+
+
s = nsecs / NSEC_PER_SEC;
ns = nsecs - s * NSEC_PER_SEC;
 
@@ -445,7 +451,7 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
 
-   if (handler) {
+   if (!dict) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
@@ -484,23 +490,23 @@ static void python_process_tracepoint(struct perf_sample 
*sample,
} else { /* FIELD_IS_NUMERIC */
obj = get_field_numeric_entry(event, field, data);
}
-   if (handler)
+   if (!dict)
PyTuple_SetItem(t, n++, obj);
else
pydict_set_item_string_decref(dict, field->name, obj);
 
}
 
-   if (!handler)
+   if (dict)
PyTuple_SetItem(t, n++, dict);
 
if (_PyTuple_Resize(, n) == -1)
Py_FatalError("error resizing Python tuple");
 
-   if (handler) {
+   if (!dict) {
call_object(handler, t, handler_name);
} else {
-   try_call_object("trace_unhandled", t);
+   call_object(handler, t, default_handler_name);
Py_DECREF(dict);
}
 
@@ -799,6 +805,12 @@ static void python_process_general_event(struct 
perf_sample *sample,
static char handler_name[64];
unsigned n = 0;
 
+   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
+
+   handler = get_handler(handler_name);
+   if (!handler)
+   return;
+
/*
 * Use the MAX_FIELDS to make the function expandable, though
 * currently there is only one item for the tuple.
@@ -815,12 +827,6 @@ static void python_process_general_event(struct 
perf_sample *sample,
if (!dict_sample)
Py_FatalError("couldn't create Python dictionary");
 
-   snprintf(handler_name, sizeof(handler_name), "%s", "process_event");
-
-   handler = get_handler(handler_name);
-   if (!handler)
-   goto exit;
-
pydict_set_item_string_decref(dict, "ev_name", 
PyString_FromString(perf_evsel__name(evsel)));
pydict_set_item_string_decref(dict, "attr", PyString_FromStringAndSize(
(const char *)>attr, sizeof(evsel->attr)));
@@ -861,7 +867,7 @@ static void python_process_general_event(struct perf_sample 
*sample,
Py_FatalError("error resizing Python tuple");
 
call_object(handler, t, handler_name);
-exit:
+
Py_DECREF(dict);
Py_DECREF(t);
 }
-- 
2.13.2.932.g7449e964c-goog



[RFC 4/4] perf script python: Generate hooks with additional argument

2017-07-17 Thread Arun Kalyanasundaram
Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram <arunk...@google.com>
---
 .../perf/util/scripting-engines/trace-event-python.c | 20 +---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index a23f5940f826..2fef0cb0383c 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1312,6 +1312,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1381,6 +1387,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1391,16 +1400,21 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
"(event_name, cpu, secs, nsecs, pid, comm),\n");
 
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])");
+
fclose(ofp);
 
fprintf(stderr, "generated Python script: %s\n", fname);
-- 
2.13.2.932.g7449e964c-goog



[RFC 0/4] perf script python: Provide perf_sample dict to all handlers

2017-07-17 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample entries.

Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate the 
introduction of this dict and do not receive it. This patch series adds the 
dict to all handlers, aiming to unify the information passed to them.

This change adds an additional argument to the affected handlers. To keep 
backwards compatibility (and avoid unnecessary work), do not pass the 
aforementioned dict if the number of arguments signals that handler version 
predates this change.

Initial Discussion: https://lkml.org/lkml/2017/7/1/108

Arun Kalyanasundaram (4):
  perf script python: Allocate memory only if handler exists
  perf script python: Refactor creation of perf sample dict
  perf script python: Add perf_sample dict to tracepoint handlers
  perf script python: Generate hooks with additional argument

 .../util/scripting-engines/trace-event-python.c| 189 ++---
 1 file changed, 128 insertions(+), 61 deletions(-)

-- 
2.13.2.932.g7449e964c-goog



[RFC 4/4] perf script python: Generate hooks with additional argument

2017-07-17 Thread Arun Kalyanasundaram
Modify the signature of tracepoint specific and trace_unhandled hooks to
add the perf_sample dict as a new argument.
Create a python helper function to print a dictionary.

Signed-off-by: Arun Kalyanasundaram 
---
 .../perf/util/scripting-engines/trace-event-python.c | 20 +---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/tools/perf/util/scripting-engines/trace-event-python.c 
b/tools/perf/util/scripting-engines/trace-event-python.c
index a23f5940f826..2fef0cb0383c 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -1312,6 +1312,12 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, "%s", f->name);
}
+   if (not_first++)
+   fprintf(ofp, ", ");
+   if (++count % 5 == 0)
+   fprintf(ofp, "\n\t\t");
+   fprintf(ofp, "perf_sample_dict");
+
fprintf(ofp, "):\n");
 
fprintf(ofp, "\t\tprint_header(event_name, common_cpu, "
@@ -1381,6 +1387,9 @@ static int python_generate_script(struct pevent *pevent, 
const char *outfile)
 
fprintf(ofp, ")\n\n");
 
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', 
')+'}'\n\n");
+
fprintf(ofp, "\t\tfor node in common_callchain:");
fprintf(ofp, "\n\t\t\tif 'sym' in node:");
fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], 
node['sym']['name'])");
@@ -1391,16 +1400,21 @@ static int python_generate_script(struct pevent 
*pevent, const char *outfile)
}
 
fprintf(ofp, "def trace_unhandled(event_name, context, "
-   "event_fields_dict):\n");
+   "event_fields_dict, perf_sample_dict):\n");
 
-   fprintf(ofp, "\t\tprint ' '.join(['%%s=%%s'%%(k,str(v))"
-   "for k,v in sorted(event_fields_dict.items())])\n\n");
+   fprintf(ofp, "\t\tprint get_dict_as_string(event_fields_dict)\n");
+   fprintf(ofp, "\t\tprint 'Sample: {'+"
+   "get_dict_as_string(perf_sample_dict['sample'], ', ')+'}'\n\n");
 
fprintf(ofp, "def print_header("
"event_name, cpu, secs, nsecs, pid, comm):\n"
"\tprint \"%%-20s %%5u %%05u.%%09u %%8u %%-20s \" %% \\\n\t"
"(event_name, cpu, secs, nsecs, pid, comm),\n");
 
+   fprintf(ofp, "def get_dict_as_string(a_dict, delimiter=' '):\n"
+   "\treturn delimiter.join"
+   "(['%%s=%%s'%%(k,str(v))for k,v in sorted(a_dict.items())])");
+
fclose(ofp);
 
fprintf(stderr, "generated Python script: %s\n", fname);
-- 
2.13.2.932.g7449e964c-goog



[RFC 0/4] perf script python: Provide perf_sample dict to all handlers

2017-07-17 Thread Arun Kalyanasundaram
The process_event python hook receives a dict with all perf_sample entries.

Other handlers (e.g. trace_unhandled, python_process_tracepoint) predate the 
introduction of this dict and do not receive it. This patch series adds the 
dict to all handlers, aiming to unify the information passed to them.

This change adds an additional argument to the affected handlers. To keep 
backwards compatibility (and avoid unnecessary work), do not pass the 
aforementioned dict if the number of arguments signals that handler version 
predates this change.

Initial Discussion: https://lkml.org/lkml/2017/7/1/108

Arun Kalyanasundaram (4):
  perf script python: Allocate memory only if handler exists
  perf script python: Refactor creation of perf sample dict
  perf script python: Add perf_sample dict to tracepoint handlers
  perf script python: Generate hooks with additional argument

 .../util/scripting-engines/trace-event-python.c| 189 ++---
 1 file changed, 128 insertions(+), 61 deletions(-)

-- 
2.13.2.932.g7449e964c-goog



Re: tracing/kprobes: [Bug] Identical timestamps on two kprobes that are few instructions apart

2017-07-10 Thread Arun Kalyanasundaram
Hi Masama,

Thank you for looking into this.
You are right, I don't see the issue when my trace_clock = x86-tsc.

I tried with other clocks and apparently, I only see this when my
clock is either perf or global.
You mentioned this happens when "it adjusts timestamp", so does that
mean this is an expected behavior in this case?

I am running this on a haswell x86 architecture with 72 cores.

Thank you,
- Arun




On Sun, Jul 9, 2017 at 5:18 PM, Masami Hiramatsu <mhira...@kernel.org> wrote:
> Hello Arun,
>
> On Fri, 7 Jul 2017 16:06:40 -0700
> Arun Kalyanasundaram <arunk...@google.com> wrote:
>
>> Hi Steven,
>>
>> Thank you very much for your reply. I am using kernel - v4.12-rc3.
>>
>> I did something like this and see the issue:
>> # trace-cmd record -e kprobes:s1 -e kprobes:s2 -- taskset -c 0 my_program
>> # ./trace-cmd report -t --cpu 0
>>
>> The issue is pretty intermittent and only happens when there are a lot
>> of samples, and so "my_program" generates a few hundred threads. Any
>> pointers on debugging this would be very helpful, or please let me
>> know if you want me to collect any log messages.
>
> Ok, so this happens with ftrace+trace-cmd too.
> If you run it on x86-64, could you add "-C x86-tsc" and check still
> it happens? If not, I guess it happens when it adjusts timestamp.
>
> Thank you,
>
> --
> Masami Hiramatsu <mhira...@kernel.org>


Re: tracing/kprobes: [Bug] Identical timestamps on two kprobes that are few instructions apart

2017-07-10 Thread Arun Kalyanasundaram
Hi Masama,

Thank you for looking into this.
You are right, I don't see the issue when my trace_clock = x86-tsc.

I tried with other clocks and apparently, I only see this when my
clock is either perf or global.
You mentioned this happens when "it adjusts timestamp", so does that
mean this is an expected behavior in this case?

I am running this on a haswell x86 architecture with 72 cores.

Thank you,
- Arun




On Sun, Jul 9, 2017 at 5:18 PM, Masami Hiramatsu  wrote:
> Hello Arun,
>
> On Fri, 7 Jul 2017 16:06:40 -0700
> Arun Kalyanasundaram  wrote:
>
>> Hi Steven,
>>
>> Thank you very much for your reply. I am using kernel - v4.12-rc3.
>>
>> I did something like this and see the issue:
>> # trace-cmd record -e kprobes:s1 -e kprobes:s2 -- taskset -c 0 my_program
>> # ./trace-cmd report -t --cpu 0
>>
>> The issue is pretty intermittent and only happens when there are a lot
>> of samples, and so "my_program" generates a few hundred threads. Any
>> pointers on debugging this would be very helpful, or please let me
>> know if you want me to collect any log messages.
>
> Ok, so this happens with ftrace+trace-cmd too.
> If you run it on x86-64, could you add "-C x86-tsc" and check still
> it happens? If not, I guess it happens when it adjusts timestamp.
>
> Thank you,
>
> --
> Masami Hiramatsu 


Re: tracing/kprobes: [Bug] Identical timestamps on two kprobes that are few instructions apart

2017-07-07 Thread Arun Kalyanasundaram
Hi Steven,

Thank you very much for your reply. I am using kernel - v4.12-rc3.

I did something like this and see the issue:
# trace-cmd record -e kprobes:s1 -e kprobes:s2 -- taskset -c 0 my_program
# ./trace-cmd report -t --cpu 0

The issue is pretty intermittent and only happens when there are a lot
of samples, and so "my_program" generates a few hundred threads. Any
pointers on debugging this would be very helpful, or please let me
know if you want me to collect any log messages.

On Fri, Jul 7, 2017 at 12:01 PM, Steven Rostedt <rost...@goodmis.org> wrote:
> On Fri, 7 Jul 2017 10:34:48 -0700
> Arun Kalyanasundaram <arunk...@google.com> wrote:
>
>> Hi,
>>
>> I am trying to use kprobes to time a few kernel functions. However, when I
>> add two kprobes on a function that are a few instructions apart, I
>> sometimes get the same timestamp (measured in nano seconds) on the two
>> probes.
>>
>> For example, if I add the two probes as follows,
>> 1) perf probe -a "kprobe1=__schedule"
>> 2) perf probe -a "kprobe2=__schedule+12"
>>
>> I then use "perf record" on a multi-threaded benchmark (e.g. stream:
>> https://www.cs.virginia.edu/stream/) to collect samples. I then see the
>> same timestamp on kprobe1 and kprobe2 for the same thread running on the
>> same CPU. Following is an example of the output showing the same timestamp
>> on the two probes.
>>
>> comm,tid,cpu,time,event,ip,sym
>> stream,62182,[064],3020935.384132080,probe:kprobe1,b36399f1,__schedule
>> stream,62182,[064],3020935.384132080,probe:kprobe2,b36399fd,__schedule
>>
>> Since it happens intermittently, I am wondering if there is some sort of
>> race condition here. Please let me know if this is an expected behavior or
>> is there something wrong in the way I use kprobes.
>>
>
> I don't see this with ftrace. What kernel are you using?
>
>  # cd /sys/kernel/debug/tracing
>  # echo perf > trace_clock
>  # echo 'p:s1 __schedule' > kprobe_events
>  # echo 'p:s2 __schedule+12' >> kprobe_events
>  # echo 1 > events/kprobes/enable
>  # cd
>  # trace-cmd extract
>  # trace-cmd report -t --cpu 0 | less
>
> I didn't see anything where they had the same timestamps.
>
>
> -- Steve


Re: tracing/kprobes: [Bug] Identical timestamps on two kprobes that are few instructions apart

2017-07-07 Thread Arun Kalyanasundaram
Hi Steven,

Thank you very much for your reply. I am using kernel - v4.12-rc3.

I did something like this and see the issue:
# trace-cmd record -e kprobes:s1 -e kprobes:s2 -- taskset -c 0 my_program
# ./trace-cmd report -t --cpu 0

The issue is pretty intermittent and only happens when there are a lot
of samples, and so "my_program" generates a few hundred threads. Any
pointers on debugging this would be very helpful, or please let me
know if you want me to collect any log messages.

On Fri, Jul 7, 2017 at 12:01 PM, Steven Rostedt  wrote:
> On Fri, 7 Jul 2017 10:34:48 -0700
> Arun Kalyanasundaram  wrote:
>
>> Hi,
>>
>> I am trying to use kprobes to time a few kernel functions. However, when I
>> add two kprobes on a function that are a few instructions apart, I
>> sometimes get the same timestamp (measured in nano seconds) on the two
>> probes.
>>
>> For example, if I add the two probes as follows,
>> 1) perf probe -a "kprobe1=__schedule"
>> 2) perf probe -a "kprobe2=__schedule+12"
>>
>> I then use "perf record" on a multi-threaded benchmark (e.g. stream:
>> https://www.cs.virginia.edu/stream/) to collect samples. I then see the
>> same timestamp on kprobe1 and kprobe2 for the same thread running on the
>> same CPU. Following is an example of the output showing the same timestamp
>> on the two probes.
>>
>> comm,tid,cpu,time,event,ip,sym
>> stream,62182,[064],3020935.384132080,probe:kprobe1,b36399f1,__schedule
>> stream,62182,[064],3020935.384132080,probe:kprobe2,b36399fd,__schedule
>>
>> Since it happens intermittently, I am wondering if there is some sort of
>> race condition here. Please let me know if this is an expected behavior or
>> is there something wrong in the way I use kprobes.
>>
>
> I don't see this with ftrace. What kernel are you using?
>
>  # cd /sys/kernel/debug/tracing
>  # echo perf > trace_clock
>  # echo 'p:s1 __schedule' > kprobe_events
>  # echo 'p:s2 __schedule+12' >> kprobe_events
>  # echo 1 > events/kprobes/enable
>  # cd
>  # trace-cmd extract
>  # trace-cmd report -t --cpu 0 | less
>
> I didn't see anything where they had the same timestamps.
>
>
> -- Steve


[Resend: Adding linux-kernel] tracing/kprobes: [Bug] Identical timestamps on two kprobes that are few instructions apart

2017-07-07 Thread Arun Kalyanasundaram
Hi,

I am trying to use kprobes to time a few kernel functions. However,
when I add two kprobes on a function that are a few instructions
apart, I sometimes get the same timestamp (measured in nano seconds)
on the two probes.

For example, if I add the two probes as follows,
1) perf probe -a "kprobe1=__schedule"
2) perf probe -a "kprobe2=__schedule+12"

I then use "perf record" on a multi-threaded benchmark (e.g.
www.cs.virginia.edu/stream/) to collect samples. I then see the same
timestamp on kprobe1 and kprobe2 for the same thread running on the
same CPU. Following is an example of the output showing the same
timestamp on the two probes.

comm,tid,cpu,time,event,ip,sym
stream,62182,[064],3020935.384132080,probe:kprobe1,b36399f1,__schedule
stream,62182,[064],3020935.384132080,probe:kprobe2,b36399fd,__schedule

Since it happens intermittently, I am wondering if there is some sort
of race condition here. Please let me know if this is an expected
behavior or is there something wrong in the way I use kprobes.

Thank you,
- Arun


[Resend: Adding linux-kernel] tracing/kprobes: [Bug] Identical timestamps on two kprobes that are few instructions apart

2017-07-07 Thread Arun Kalyanasundaram
Hi,

I am trying to use kprobes to time a few kernel functions. However,
when I add two kprobes on a function that are a few instructions
apart, I sometimes get the same timestamp (measured in nano seconds)
on the two probes.

For example, if I add the two probes as follows,
1) perf probe -a "kprobe1=__schedule"
2) perf probe -a "kprobe2=__schedule+12"

I then use "perf record" on a multi-threaded benchmark (e.g.
www.cs.virginia.edu/stream/) to collect samples. I then see the same
timestamp on kprobe1 and kprobe2 for the same thread running on the
same CPU. Following is an example of the output showing the same
timestamp on the two probes.

comm,tid,cpu,time,event,ip,sym
stream,62182,[064],3020935.384132080,probe:kprobe1,b36399f1,__schedule
stream,62182,[064],3020935.384132080,probe:kprobe2,b36399fd,__schedule

Since it happens intermittently, I am wondering if there is some sort
of race condition here. Please let me know if this is an expected
behavior or is there something wrong in the way I use kprobes.

Thank you,
- Arun


Re: perf script: Question: Python trace processing script contains the tid of the process in the common_pid attribute

2017-07-05 Thread Arun Kalyanasundaram
Arnaldo:
So, I think what you are suggesting is, we should check the signature
of the hook to determine if it has an additional attribute and only
then should we provide the dict. May be something like this:

PyObject* custom_dict = PyObject_GetAttrString(handler, "other_fields_dict");
if (custom_dict)
//Add dict to PyTuple

Do you think this would be a better approach?

Thank you,
- Arun

On Wed, Jul 5, 2017 at 1:41 PM, Arun Kalyanasundaram
<arunk...@google.com> wrote:
> I wasn't entirely sure if we should modify the signature of the python
> hooks_  as this would make existing scripts incompatible. So the patch
> only adds sample->pid to the event_fields_dict param in
> trace_unhandled().
>
>
> On Wed, Jul 5, 2017 at 12:26 PM, Arnaldo Carvalho de Melo
> <a...@kernel.org> wrote:
>> Em Wed, Jul 05, 2017 at 04:25:45PM -0300, Arnaldo Carvalho de Melo escreveu:
>>> Em Wed, Jul 05, 2017 at 09:22:07AM -0700, Arun Kalyanasundaram escreveu:
>>> > Hi Arnaldo,
>>> >
>>> > Thank you for your reply.
>>> > I actually meant tracepoint event handlers: def
>>> > trace_unhandled(event_name, context, event_fields_dict)
>>> > The dict parameter contains an attribute "common_pid" which is
>>> > actually the "tid" of the thread. There are no other attributes that
>>> > contain the actual pid of the process. So, I was wondering if this is
>>> > something intentional? If not I can share a patch to fix this.
>>>
>>> Yeah there is a problem in:
>>>
>>> tools/perf/util/scripting-engines/trace-event-python.c
>>>
>>> static void python_process_event(union perf_event *event,
>>>  struct perf_sample *sample,
>>>  struct perf_evsel *evsel,
>>>  struct addr_location *al)
>>> {
>>> struct tables *tables = _global;
>>>
>>> switch (evsel->attr.type) {
>>> case PERF_TYPE_TRACEPOINT:
>>> python_process_tracepoint(sample, evsel, al);
>>> break;
>>> /* Reserve for future process_hw/sw/raw APIs */
>>> default:
>>> if (tables->db_export_mode)
>>> db_export__sample(>dbe, event, sample, 
>>> evsel, al);
>>> else
>>> python_process_general_event(sample, evsel, al);
>>> }
>>> }
>>>
>>> The python_process_tracepoint() thing predates
>>> python_process_general_event(), and doesn't adds the dict with all the
>>> perf_sample entries that python_process_general_event() passes to the
>>> python method :-\
>>>
>>> Both the per-tracepoint python hooks _and_ trace_unhandled() should get
>>> that dict, is that what your patch does?
>>
>> Well, for performance reasons I think perhaps we could take a look at
>> the signature of the python hook and provide the dictionary only if it
>> is in it?
>>
>> - Arnaldo


Re: perf script: Question: Python trace processing script contains the tid of the process in the common_pid attribute

2017-07-05 Thread Arun Kalyanasundaram
Arnaldo:
So, I think what you are suggesting is, we should check the signature
of the hook to determine if it has an additional attribute and only
then should we provide the dict. May be something like this:

PyObject* custom_dict = PyObject_GetAttrString(handler, "other_fields_dict");
if (custom_dict)
//Add dict to PyTuple

Do you think this would be a better approach?

Thank you,
- Arun

On Wed, Jul 5, 2017 at 1:41 PM, Arun Kalyanasundaram
 wrote:
> I wasn't entirely sure if we should modify the signature of the python
> hooks_  as this would make existing scripts incompatible. So the patch
> only adds sample->pid to the event_fields_dict param in
> trace_unhandled().
>
>
> On Wed, Jul 5, 2017 at 12:26 PM, Arnaldo Carvalho de Melo
>  wrote:
>> Em Wed, Jul 05, 2017 at 04:25:45PM -0300, Arnaldo Carvalho de Melo escreveu:
>>> Em Wed, Jul 05, 2017 at 09:22:07AM -0700, Arun Kalyanasundaram escreveu:
>>> > Hi Arnaldo,
>>> >
>>> > Thank you for your reply.
>>> > I actually meant tracepoint event handlers: def
>>> > trace_unhandled(event_name, context, event_fields_dict)
>>> > The dict parameter contains an attribute "common_pid" which is
>>> > actually the "tid" of the thread. There are no other attributes that
>>> > contain the actual pid of the process. So, I was wondering if this is
>>> > something intentional? If not I can share a patch to fix this.
>>>
>>> Yeah there is a problem in:
>>>
>>> tools/perf/util/scripting-engines/trace-event-python.c
>>>
>>> static void python_process_event(union perf_event *event,
>>>  struct perf_sample *sample,
>>>  struct perf_evsel *evsel,
>>>  struct addr_location *al)
>>> {
>>> struct tables *tables = _global;
>>>
>>> switch (evsel->attr.type) {
>>> case PERF_TYPE_TRACEPOINT:
>>> python_process_tracepoint(sample, evsel, al);
>>> break;
>>> /* Reserve for future process_hw/sw/raw APIs */
>>> default:
>>> if (tables->db_export_mode)
>>> db_export__sample(>dbe, event, sample, 
>>> evsel, al);
>>> else
>>> python_process_general_event(sample, evsel, al);
>>> }
>>> }
>>>
>>> The python_process_tracepoint() thing predates
>>> python_process_general_event(), and doesn't adds the dict with all the
>>> perf_sample entries that python_process_general_event() passes to the
>>> python method :-\
>>>
>>> Both the per-tracepoint python hooks _and_ trace_unhandled() should get
>>> that dict, is that what your patch does?
>>
>> Well, for performance reasons I think perhaps we could take a look at
>> the signature of the python hook and provide the dictionary only if it
>> is in it?
>>
>> - Arnaldo


Re: perf script: Question: Python trace processing script contains the tid of the process in the common_pid attribute

2017-07-05 Thread Arun Kalyanasundaram
I wasn't entirely sure if we should modify the signature of the python
hooks_  as this would make existing scripts incompatible. So the patch
only adds sample->pid to the event_fields_dict param in
trace_unhandled().


On Wed, Jul 5, 2017 at 12:26 PM, Arnaldo Carvalho de Melo
<a...@kernel.org> wrote:
> Em Wed, Jul 05, 2017 at 04:25:45PM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Wed, Jul 05, 2017 at 09:22:07AM -0700, Arun Kalyanasundaram escreveu:
>> > Hi Arnaldo,
>> >
>> > Thank you for your reply.
>> > I actually meant tracepoint event handlers: def
>> > trace_unhandled(event_name, context, event_fields_dict)
>> > The dict parameter contains an attribute "common_pid" which is
>> > actually the "tid" of the thread. There are no other attributes that
>> > contain the actual pid of the process. So, I was wondering if this is
>> > something intentional? If not I can share a patch to fix this.
>>
>> Yeah there is a problem in:
>>
>> tools/perf/util/scripting-engines/trace-event-python.c
>>
>> static void python_process_event(union perf_event *event,
>>  struct perf_sample *sample,
>>  struct perf_evsel *evsel,
>>  struct addr_location *al)
>> {
>> struct tables *tables = _global;
>>
>> switch (evsel->attr.type) {
>> case PERF_TYPE_TRACEPOINT:
>> python_process_tracepoint(sample, evsel, al);
>> break;
>> /* Reserve for future process_hw/sw/raw APIs */
>> default:
>> if (tables->db_export_mode)
>> db_export__sample(>dbe, event, sample, 
>> evsel, al);
>> else
>> python_process_general_event(sample, evsel, al);
>> }
>> }
>>
>> The python_process_tracepoint() thing predates
>> python_process_general_event(), and doesn't adds the dict with all the
>> perf_sample entries that python_process_general_event() passes to the
>> python method :-\
>>
>> Both the per-tracepoint python hooks _and_ trace_unhandled() should get
>> that dict, is that what your patch does?
>
> Well, for performance reasons I think perhaps we could take a look at
> the signature of the python hook and provide the dictionary only if it
> is in it?
>
> - Arnaldo


Re: perf script: Question: Python trace processing script contains the tid of the process in the common_pid attribute

2017-07-05 Thread Arun Kalyanasundaram
I wasn't entirely sure if we should modify the signature of the python
hooks_  as this would make existing scripts incompatible. So the patch
only adds sample->pid to the event_fields_dict param in
trace_unhandled().


On Wed, Jul 5, 2017 at 12:26 PM, Arnaldo Carvalho de Melo
 wrote:
> Em Wed, Jul 05, 2017 at 04:25:45PM -0300, Arnaldo Carvalho de Melo escreveu:
>> Em Wed, Jul 05, 2017 at 09:22:07AM -0700, Arun Kalyanasundaram escreveu:
>> > Hi Arnaldo,
>> >
>> > Thank you for your reply.
>> > I actually meant tracepoint event handlers: def
>> > trace_unhandled(event_name, context, event_fields_dict)
>> > The dict parameter contains an attribute "common_pid" which is
>> > actually the "tid" of the thread. There are no other attributes that
>> > contain the actual pid of the process. So, I was wondering if this is
>> > something intentional? If not I can share a patch to fix this.
>>
>> Yeah there is a problem in:
>>
>> tools/perf/util/scripting-engines/trace-event-python.c
>>
>> static void python_process_event(union perf_event *event,
>>  struct perf_sample *sample,
>>  struct perf_evsel *evsel,
>>  struct addr_location *al)
>> {
>> struct tables *tables = _global;
>>
>> switch (evsel->attr.type) {
>> case PERF_TYPE_TRACEPOINT:
>> python_process_tracepoint(sample, evsel, al);
>> break;
>> /* Reserve for future process_hw/sw/raw APIs */
>> default:
>> if (tables->db_export_mode)
>> db_export__sample(>dbe, event, sample, 
>> evsel, al);
>> else
>> python_process_general_event(sample, evsel, al);
>> }
>> }
>>
>> The python_process_tracepoint() thing predates
>> python_process_general_event(), and doesn't adds the dict with all the
>> perf_sample entries that python_process_general_event() passes to the
>> python method :-\
>>
>> Both the per-tracepoint python hooks _and_ trace_unhandled() should get
>> that dict, is that what your patch does?
>
> Well, for performance reasons I think perhaps we could take a look at
> the signature of the python hook and provide the dictionary only if it
> is in it?
>
> - Arnaldo


Re: perf script: Question: Python trace processing script contains the tid of the process in the common_pid attribute

2017-07-05 Thread Arun Kalyanasundaram
Hi Arnaldo,

Thank you for your reply.
I actually meant tracepoint event handlers: def
trace_unhandled(event_name, context, event_fields_dict)
The dict parameter contains an attribute "common_pid" which is
actually the "tid" of the thread. There are no other attributes that
contain the actual pid of the process. So, I was wondering if this is
something intentional? If not I can share a patch to fix this.

Best,
- Arun


On Sat, Jul 1, 2017 at 7:47 AM, Arnaldo Carvalho de Melo
<a...@redhat.com> wrote:
> Em Fri, Jun 30, 2017 at 03:40:57PM -0700, Arun Kalyanasundaram escreveu:
>> The handlers in the python script generated from "perf script" have an
>> attribute: common_pid. This attribute contains the tid of the process
>> instead of its pid. I would like to know if this is the expected behavior.
>> There are no other attributes in the Python handler that provide the pid
>> and knowing the process id is useful to be able to group all samples that
>> belong to the same process that generated different threads.
>
> Humm, you have:
>
> def process_event(param_dict):
> event_attr = param_dict["attr"]
> sample = param_dict["sample"]
> raw_buf= param_dict["raw_buf"]
> comm   = param_dict["comm"]
> name   = param_dict["ev_name"]
>
> And then, on sample you have (from a recent python script for processing
> Intel PT samples):
>
> def print_common_start(comm, sample, name):
>ts = sample["time"]
>cpu = sample["cpu"]
>pid = sample["pid"]
>tid = sample["tid"]
>print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts 
> / 10, ts %10, name),
>
> - Arnaldo


Re: perf script: Question: Python trace processing script contains the tid of the process in the common_pid attribute

2017-07-05 Thread Arun Kalyanasundaram
Hi Arnaldo,

Thank you for your reply.
I actually meant tracepoint event handlers: def
trace_unhandled(event_name, context, event_fields_dict)
The dict parameter contains an attribute "common_pid" which is
actually the "tid" of the thread. There are no other attributes that
contain the actual pid of the process. So, I was wondering if this is
something intentional? If not I can share a patch to fix this.

Best,
- Arun


On Sat, Jul 1, 2017 at 7:47 AM, Arnaldo Carvalho de Melo
 wrote:
> Em Fri, Jun 30, 2017 at 03:40:57PM -0700, Arun Kalyanasundaram escreveu:
>> The handlers in the python script generated from "perf script" have an
>> attribute: common_pid. This attribute contains the tid of the process
>> instead of its pid. I would like to know if this is the expected behavior.
>> There are no other attributes in the Python handler that provide the pid
>> and knowing the process id is useful to be able to group all samples that
>> belong to the same process that generated different threads.
>
> Humm, you have:
>
> def process_event(param_dict):
> event_attr = param_dict["attr"]
> sample = param_dict["sample"]
> raw_buf= param_dict["raw_buf"]
> comm   = param_dict["comm"]
> name   = param_dict["ev_name"]
>
> And then, on sample you have (from a recent python script for processing
> Intel PT samples):
>
> def print_common_start(comm, sample, name):
>ts = sample["time"]
>cpu = sample["cpu"]
>pid = sample["pid"]
>tid = sample["tid"]
>print "%16s %5u/%-5u [%03u] %9u.%09u %7s:" % (comm, pid, tid, cpu, ts 
> / 10, ts %10, name),
>
> - Arnaldo


Re: [PATCH v2]: perf/core: addressing 4x slowdown during per-process, profiling of STREAM benchmark on Intel Xeon Phi

2017-05-30 Thread Arun Kalyanasundaram
Hi Alexey,

I am interested in validating this fix. Can you please share some of
your testcases or let me know if you use any standard OpenMP
benchmarks?

- Arun


Re: [PATCH v2]: perf/core: addressing 4x slowdown during per-process, profiling of STREAM benchmark on Intel Xeon Phi

2017-05-30 Thread Arun Kalyanasundaram
Hi Alexey,

I am interested in validating this fix. Can you please share some of
your testcases or let me know if you use any standard OpenMP
benchmarks?

- Arun