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>
This commit is contained in:
Joseph Schuchart 2014-07-10 13:50:51 +02:00 committed by Arnaldo Carvalho de Melo
parent 05f832e3a2
commit 0f5f5bcd11
11 changed files with 146 additions and 48 deletions

View file

@ -32,6 +32,7 @@
#include "../event.h"
#include "../thread.h"
#include "../trace-event.h"
#include "../machine.h"
PyMODINIT_FUNC initperf_trace_context(void);
@ -278,12 +279,90 @@ static PyObject *get_field_numeric_entry(struct event_format *event,
return obj;
}
static PyObject *python_process_callchain(struct perf_sample *sample,
struct perf_evsel *evsel,
struct addr_location *al)
{
PyObject *pylist;
pylist = PyList_New(0);
if (!pylist)
Py_FatalError("couldn't create Python list");
if (!symbol_conf.use_callchain || !sample->callchain)
goto exit;
if (machine__resolve_callchain(al->machine, evsel, al->thread,
sample, NULL, NULL,
PERF_MAX_STACK_DEPTH) != 0) {
pr_err("Failed to resolve callchain. Skipping\n");
goto exit;
}
callchain_cursor_commit(&callchain_cursor);
while (1) {
PyObject *pyelem;
struct callchain_cursor_node *node;
node = callchain_cursor_current(&callchain_cursor);
if (!node)
break;
pyelem = PyDict_New();
if (!pyelem)
Py_FatalError("couldn't create Python dictionary");
pydict_set_item_string_decref(pyelem, "ip",
PyLong_FromUnsignedLongLong(node->ip));
if (node->sym) {
PyObject *pysym = PyDict_New();
if (!pysym)
Py_FatalError("couldn't create Python dictionary");
pydict_set_item_string_decref(pysym, "start",
PyLong_FromUnsignedLongLong(node->sym->start));
pydict_set_item_string_decref(pysym, "end",
PyLong_FromUnsignedLongLong(node->sym->end));
pydict_set_item_string_decref(pysym, "binding",
PyInt_FromLong(node->sym->binding));
pydict_set_item_string_decref(pysym, "name",
PyString_FromStringAndSize(node->sym->name,
node->sym->namelen));
pydict_set_item_string_decref(pyelem, "sym", pysym);
}
if (node->map) {
struct map *map = node->map;
const char *dsoname = "[unknown]";
if (map && map->dso && (map->dso->name || map->dso->long_name)) {
if (symbol_conf.show_kernel_path && map->dso->long_name)
dsoname = map->dso->long_name;
else if (map->dso->name)
dsoname = map->dso->name;
}
pydict_set_item_string_decref(pyelem, "dso",
PyString_FromString(dsoname));
}
callchain_cursor_advance(&callchain_cursor);
PyList_Append(pylist, pyelem);
Py_DECREF(pyelem);
}
exit:
return pylist;
}
static void python_process_tracepoint(struct perf_sample *sample,
struct perf_evsel *evsel,
struct thread *thread,
struct addr_location *al)
{
PyObject *handler, *retval, *context, *t, *obj, *dict = NULL;
PyObject *handler, *retval, *context, *t, *obj, *callchain;
PyObject *dict = NULL;
static char handler_name[256];
struct format_field *field;
unsigned long s, ns;
@ -326,18 +405,23 @@ static void python_process_tracepoint(struct perf_sample *sample,
PyTuple_SetItem(t, n++, PyString_FromString(handler_name));
PyTuple_SetItem(t, n++, context);
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
if (handler) {
PyTuple_SetItem(t, n++, PyInt_FromLong(cpu));
PyTuple_SetItem(t, n++, PyInt_FromLong(s));
PyTuple_SetItem(t, n++, PyInt_FromLong(ns));
PyTuple_SetItem(t, n++, PyInt_FromLong(pid));
PyTuple_SetItem(t, n++, PyString_FromString(comm));
PyTuple_SetItem(t, n++, callchain);
} else {
pydict_set_item_string_decref(dict, "common_cpu", PyInt_FromLong(cpu));
pydict_set_item_string_decref(dict, "common_s", PyInt_FromLong(s));
pydict_set_item_string_decref(dict, "common_ns", PyInt_FromLong(ns));
pydict_set_item_string_decref(dict, "common_pid", PyInt_FromLong(pid));
pydict_set_item_string_decref(dict, "common_comm", PyString_FromString(comm));
pydict_set_item_string_decref(dict, "common_callchain", callchain);
}
for (field = event->format.fields; field; field = field->next) {
if (field->flags & FIELD_IS_STRING) {
@ -357,6 +441,7 @@ static void python_process_tracepoint(struct perf_sample *sample,
pydict_set_item_string_decref(dict, field->name, obj);
}
if (!handler)
PyTuple_SetItem(t, n++, dict);
@ -388,7 +473,7 @@ static void python_process_general_event(struct perf_sample *sample,
struct thread *thread,
struct addr_location *al)
{
PyObject *handler, *retval, *t, *dict;
PyObject *handler, *retval, *t, *dict, *callchain;
static char handler_name[64];
unsigned n = 0;
@ -428,6 +513,10 @@ static void python_process_general_event(struct perf_sample *sample,
PyString_FromString(al->sym->name));
}
/* ip unwinding */
callchain = python_process_callchain(sample, evsel, al);
pydict_set_item_string_decref(dict, "callchain", callchain);
PyTuple_SetItem(t, n++, dict);
if (_PyTuple_Resize(&t, n) == -1)
Py_FatalError("error resizing Python tuple");
@ -624,6 +713,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "common_nsecs, ");
fprintf(ofp, "common_pid, ");
fprintf(ofp, "common_comm,\n\t");
fprintf(ofp, "common_callchain, ");
not_first = 0;
count = 0;
@ -667,7 +757,7 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%%u");
}
fprintf(ofp, "\\n\" %% \\\n\t\t(");
fprintf(ofp, "\" %% \\\n\t\t(");
not_first = 0;
count = 0;
@ -703,7 +793,15 @@ static int python_generate_script(struct pevent *pevent, const char *outfile)
fprintf(ofp, "%s", f->name);
}
fprintf(ofp, "),\n\n");
fprintf(ofp, ")\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'])");
fprintf(ofp, "\n\t\t\telse:");
fprintf(ofp, "\n\t\t\t\tprint \"\t[%%x]\" %% (node['ip'])\n\n");
fprintf(ofp, "\t\tprint \"\\n\"\n\n");
}
fprintf(ofp, "def trace_unhandled(event_name, context, "