aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/scripting-engines/trace-event-python.c
diff options
context:
space:
mode:
authorJoseph Schuchart <joseph.schuchart@tu-dresden.de>2014-07-10 07:50:51 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2014-07-16 16:57:33 -0400
commit0f5f5bcd112292f14b75750dde7461463bb1c7bb (patch)
treebb87bcdd3d703c5f397d46db0c7bd7c14d144e62 /tools/perf/util/scripting-engines/trace-event-python.c
parent05f832e3a267d6e45d092595bdf9339d127ea137 (diff)
perf script: Add callchain to generic and tracepoint events
This provides valuable information for tracing performance problems. Since this change alters the interface for the python scripts, also adjust the script generation and the provided scripts. Signed-off-by: Joseph Schuchart <joseph.schuchart@tu-dresden.de> Acked-by: Thomas Ilsche <thomas.ilsche@tu-dresden.de> Cc: Ingo Molnar <mingo@redhat.com> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Thomas Ilsche <thomas.ilsche@tu-dresden.de> Link: http://lkml.kernel.org/r/53BE7E1B.10503@tu-dresden.de Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/scripting-engines/trace-event-python.c')
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c106
1 files changed, 102 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 b6c1a69f2b18..cf65404472cb 100644
--- a/tools/perf/util/scripting-engines/trace-event-python.c
+++ b/tools/perf/util/scripting-engines/trace-event-python.c
@@ -32,6 +32,7 @@
32#include "../event.h" 32#include "../event.h"
33#include "../thread.h" 33#include "../thread.h"
34#include "../trace-event.h" 34#include "../trace-event.h"
35#include "../machine.h"
35 36
36PyMODINIT_FUNC initperf_trace_context(void); 37PyMODINIT_FUNC initperf_trace_context(void);
37 38
@@ -278,12 +279,90 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
278 return obj; 279 return obj;
279} 280}
280 281
282
283static PyObject *python_process_callchain(struct perf_sample *sample,
284 struct perf_evsel *evsel,
285 struct addr_location *al)
286{
287 PyObject *pylist;
288
289 pylist = PyList_New(0);
290 if (!pylist)
291 Py_FatalError("couldn't create Python list");
292
293 if (!symbol_conf.use_callchain || !sample->callchain)
294 goto exit;
295
296 if (machine__resolve_callchain(al->machine, evsel, al->thread,
297 sample, NULL, NULL,
298 PERF_MAX_STACK_DEPTH) != 0) {
299 pr_err("Failed to resolve callchain. Skipping\n");
300 goto exit;
301 }
302 callchain_cursor_commit(&callchain_cursor);
303
304
305 while (1) {
306 PyObject *pyelem;
307 struct callchain_cursor_node *node;
308 node = callchain_cursor_current(&callchain_cursor);
309 if (!node)
310 break;
311
312 pyelem = PyDict_New();
313 if (!pyelem)
314 Py_FatalError("couldn't create Python dictionary");
315
316
317 pydict_set_item_string_decref(pyelem, "ip",
318 PyLong_FromUnsignedLongLong(node->ip));
319
320 if (node->sym) {
321 PyObject *pysym = PyDict_New();
322 if (!pysym)
323 Py_FatalError("couldn't create Python dictionary");
324 pydict_set_item_string_decref(pysym, "start",
325 PyLong_FromUnsignedLongLong(node->sym->start));
326 pydict_set_item_string_decref(pysym, "end",
327 PyLong_FromUnsignedLongLong(node->sym->end));
328 pydict_set_item_string_decref(pysym, "binding",
329 PyInt_FromLong(node->sym->binding));
330 pydict_set_item_string_decref(pysym, "name",
331 PyString_FromStringAndSize(node->sym->name,
332 node->sym->namelen));
333 pydict_set_item_string_decref(pyelem, "sym", pysym);
334 }
335
336 if (node->map) {
337 struct map *map = node->map;
338 const char *dsoname = "[unknown]";
339 if (map && map->dso && (map->dso->name || map->dso->long_name)) {
340 if (symbol_conf.show_kernel_path && map->dso->long_name)
341 dsoname = map->dso->long_name;
342 else if (map->dso->name)
343 dsoname = map->dso->name;
344 }
345 pydict_set_item_string_decref(pyelem, "dso",
346 PyString_FromString(dsoname));
347 }
348
349 callchain_cursor_advance(&callchain_cursor);
350 PyList_Append(pylist, pyelem);
351 Py_DECREF(pyelem);
352 }
353
354exit:
355 return pylist;
356}
357
358
281static void python_process_tracepoint(struct perf_sample *sample, 359static void python_process_tracepoint(struct perf_sample *sample,
282 struct perf_evsel *evsel, 360 struct perf_evsel *evsel,
283 struct thread *thread, 361 struct thread *thread,
284 struct addr_location *al) 362 struct addr_location *al)
285{ 363{
286 PyObject *handler, *retval, *context, *t, *obj, *dict = NULL; 364 PyObject *handler, *retval, *context, *t, *obj, *callchain;
365 PyObject *dict = NULL;
287 static char handler_name[256]; 366 static char handler_name[256];
288 struct format_field *field; 367 struct format_field *field;
289 unsigned long s, ns; 368 unsigned long s, ns;
@@ -326,18 +405,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
326 PyTuple_SetItem(t, n++, PyString_FromString(handler_name)); 405 PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
327 PyTuple_SetItem(t, n++, context); 406 PyTuple_SetItem(t, n++, context);
328 407
408 /* ip unwinding */
409 callchain = python_process_callchain(sample, evsel, al);
410
329 if (handler) { 411 if (handler) {
330 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu)); 412 PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
331 PyTuple_SetItem(t, n++, PyInt_FromLong(s)); 413 PyTuple_SetItem(t, n++, PyInt_FromLong(s));
332 PyTuple_SetItem(t, n++, PyInt_FromLong(ns)); 414 PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
333 PyTuple_SetItem(t, n++, PyInt_FromLong(pid)); 415 PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
334 PyTuple_SetItem(t, n++, PyString_FromString(comm)); 416 PyTuple_SetItem(t, n++, PyString_FromString(comm));
417 PyTuple_SetItem(t, n++, callchain);
335 } else { 418 } else {
336 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu)); 419 pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
337 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s)); 420 pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
338 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns)); 421 pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
339 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid)); 422 pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
340 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm)); 423 pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
424 pydict_set_item_string_decref(dict, "common_callchain", callchain);
341 } 425 }
342 for (field = event->format.fields; field; field = field->next) { 426 for (field = event->format.fields; field; field = field->next) {
343 if (field->flags & FIELD_IS_STRING) { 427 if (field->flags & FIELD_IS_STRING) {
@@ -357,6 +441,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
357 pydict_set_item_string_decref(dict, field->name, obj); 441 pydict_set_item_string_decref(dict, field->name, obj);
358 442
359 } 443 }
444
360 if (!handler) 445 if (!handler)
361 PyTuple_SetItem(t, n++, dict); 446 PyTuple_SetItem(t, n++, dict);
362 447
@@ -388,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,
388 struct thread *thread, 473 struct thread *thread,
389 struct addr_location *al) 474 struct addr_location *al)
390{ 475{
391 PyObject *handler, *retval, *t, *dict; 476 PyObject *handler, *retval, *t, *dict, *callchain;
392 static char handler_name[64]; 477 static char handler_name[64];
393 unsigned n = 0; 478 unsigned n = 0;
394 479
@@ -428,6 +513,10 @@ static void python_process_general_event(struct perf_sample *sample,
428 PyString_FromString(al->sym->name)); 513 PyString_FromString(al->sym->name));
429 } 514 }
430 515
516 /* ip unwinding */
517 callchain = python_process_callchain(sample, evsel, al);
518 pydict_set_item_string_decref(dict, "callchain", callchain);
519
431 PyTuple_SetItem(t, n++, dict); 520 PyTuple_SetItem(t, n++, dict);
432 if (_PyTuple_Resize(&t, n) == -1) 521 if (_PyTuple_Resize(&t, n) == -1)
433 Py_FatalError("error resizing Python tuple"); 522 Py_FatalError("error resizing Python tuple");
@@ -624,6 +713,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
624 fprintf(ofp, "common_nsecs, "); 713 fprintf(ofp, "common_nsecs, ");
625 fprintf(ofp, "common_pid, "); 714 fprintf(ofp, "common_pid, ");
626 fprintf(ofp, "common_comm,\n\t"); 715 fprintf(ofp, "common_comm,\n\t");
716 fprintf(ofp, "common_callchain, ");
627 717
628 not_first = 0; 718 not_first = 0;
629 count = 0; 719 count = 0;
@@ -667,7 +757,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
667 fprintf(ofp, "%%u"); 757 fprintf(ofp, "%%u");
668 } 758 }
669 759
670 fprintf(ofp, "\\n\" %% \\\n\t\t("); 760 fprintf(ofp, "\" %% \\\n\t\t(");
671 761
672 not_first = 0; 762 not_first = 0;
673 count = 0; 763 count = 0;
@@ -703,7 +793,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
703 fprintf(ofp, "%s", f->name); 793 fprintf(ofp, "%s", f->name);
704 } 794 }
705 795
706 fprintf(ofp, "),\n\n"); 796 fprintf(ofp, ")\n\n");
797
798 fprintf(ofp, "\t\tfor node in common_callchain:");
799 fprintf(ofp, "\n\t\t\tif 'sym' in node:");
800 fprintf(ofp, "\n\t\t\t\tprint \"\\t[%%x] %%s\" %% (node['ip'], node['sym']['name'])");
801 fprintf(ofp, "\n\t\t\telse:");
802 fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
803 fprintf(ofp, "\t\tprint \"\\n\"\n\n");
804
707 } 805 }
708 806
709 fprintf(ofp, "def trace_unhandled(event_name, context, " 807 fprintf(ofp, "def trace_unhandled(event_name, context, "