Messages in this thread | | | Subject | Re: [PATCH 5/6] perf script: expose usage of the callchain db export via the python api | From | Adrian Hunter <> | Date | Fri, 6 May 2016 14:28:14 +0300 |
| |
On 28/04/16 11:19, Chris Phlipot wrote: > This change allows python scripts to be able to utilize the recent > changes to the db export api allowing the export of call_paths derived > from sampled callchains. These call paths are also now associated with > the samples from which they were derived. > > -This feature is enabled by setting "perf_db_export_callchains" to true > > -When enabled, samples that have callchain information will have the > callchains exported via call_path_table > > -The call_path_id field is added to sample_table to enable association of > samples with the corresponding callchain stored in the call paths > table. A call_path_id of 0 will be exported if there is no > corresponding callchain. > > -When "perf_db_export_callchains" and "perf_db_export_calls" are both > set to True, the call path root data structure will be shared. This > prevents duplicating of data and call path ids that would result from > building two separate call path trees in memory. > > -The call_return_processor structure definition was relocated to the header > file to make its contents visible to db-export.c. This enables the > sharing of call path trees between the two features, as mentioned > above. > > This change is visible to python scripts using the python db export api. > The change is backwards compatible with scripts written against the > previous API, assuming that the scripts model the sample_table function > after the one in export-to-postgresql.py script by allowing for additional > arguments to be added in the future. ie. using *x as the final argument of > the sample_table function. > > Signed-off-by: Chris Phlipot <cphlipot0@gmail.com>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
> --- > .../util/scripting-engines/trace-event-python.c | 35 ++++++++++++++++++++-- > tools/perf/util/thread-stack.c | 13 -------- > tools/perf/util/thread-stack.h | 14 ++++++++- > 3 files changed, 46 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 7bb8592..091bce6 100644 > --- a/tools/perf/util/scripting-engines/trace-event-python.c > +++ b/tools/perf/util/scripting-engines/trace-event-python.c > @@ -682,7 +682,7 @@ static int python_export_sample(struct db_export *dbe, > struct tables *tables = container_of(dbe, struct tables, dbe); > PyObject *t; > > - t = tuple_new(21); > + t = tuple_new(22); > > tuple_set_u64(t, 0, es->db_id); > tuple_set_u64(t, 1, es->evsel->db_id); > @@ -705,6 +705,7 @@ static int python_export_sample(struct db_export *dbe, > tuple_set_u64(t, 18, es->sample->data_src); > tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); > tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); > + tuple_set_u64(t, 21, es->call_path_id); > > call_object(tables->sample_handler, t, "sample_table"); > > @@ -999,8 +1000,10 @@ static void set_table_handlers(struct tables *tables) > { > const char *perf_db_export_mode = "perf_db_export_mode"; > const char *perf_db_export_calls = "perf_db_export_calls"; > - PyObject *db_export_mode, *db_export_calls; > + const char *perf_db_export_callchains = "perf_db_export_callchains"; > + PyObject *db_export_mode, *db_export_calls, *db_export_callchains; > bool export_calls = false; > + bool export_callchains = false; > int ret; > > memset(tables, 0, sizeof(struct tables)); > @@ -1017,6 +1020,7 @@ static void set_table_handlers(struct tables *tables) > if (!ret) > return; > > + /* handle export calls */ > tables->dbe.crp = NULL; > db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); > if (db_export_calls) { > @@ -1034,6 +1038,33 @@ static void set_table_handlers(struct tables *tables) > Py_FatalError("failed to create calls processor"); > } > > + /* handle export callchains */ > + tables->dbe.cpr = NULL; > + db_export_callchains = PyDict_GetItemString(main_dict, > + perf_db_export_callchains); > + if (db_export_callchains) { > + ret = PyObject_IsTrue(db_export_callchains); > + if (ret == -1) > + handler_call_die(perf_db_export_callchains); > + export_callchains = !!ret; > + } > + > + if (export_callchains) { > + /* > + * Attempt to use the call path root from the call return > + * processor, if the call return processor is in use. Otherwise, > + * we allocate a new call path root. This prevents exporting > + * duplicate call path ids when both are in use simultaniously. > + */ > + if (tables->dbe.crp) > + tables->dbe.cpr = tables->dbe.crp->cpr; > + else > + tables->dbe.cpr = call_path_root__new(); > + > + if (!tables->dbe.cpr) > + Py_FatalError("failed to create calls processor"); > + } > + > tables->db_export_mode = true; > /* > * Reserve per symbol space for symbol->db_id via symbol__priv() > diff --git a/tools/perf/util/thread-stack.c b/tools/perf/util/thread-stack.c > index fc419a5..825086a 100644 > --- a/tools/perf/util/thread-stack.c > +++ b/tools/perf/util/thread-stack.c > @@ -25,19 +25,6 @@ > #include "call-path.h" > #include "thread-stack.h" > > -/** > - * struct call_return_processor - provides a call-back to consume call-return > - * information. > - * @cpr: call path root > - * @process: call-back that accepts call/return information > - * @data: anonymous data for call-back > - */ > -struct call_return_processor { > - struct call_path_root *cpr; > - int (*process)(struct call_return *cr, void *data); > - void *data; > -}; > - > #define STACK_GROWTH 2048 > > /** > diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h > index ec9bedd..ad44c79 100644 > --- a/tools/perf/util/thread-stack.h > +++ b/tools/perf/util/thread-stack.h > @@ -25,7 +25,6 @@ struct comm; > struct ip_callchain; > struct symbol; > struct dso; > -struct call_return_processor; > struct comm; > struct perf_sample; > struct addr_location; > @@ -68,6 +67,19 @@ struct call_return { > u32 flags; > }; > > +/** > + * struct call_return_processor - provides a call-back to consume call-return > + * information. > + * @cpr: call path root > + * @process: call-back that accepts call/return information > + * @data: anonymous data for call-back > + */ > +struct call_return_processor { > + struct call_path_root *cpr; > + int (*process)(struct call_return *cr, void *data); > + void *data; > +}; > + > int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, > u64 to_ip, u16 insn_len, u64 trace_nr); > void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); >
| |