Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf script: Expose usage of the callchain db export via the python api

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>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: http://lkml.kernel.org/r/1461831551-12213-6-git-send-email-cphlipot0@gmail.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Chris Phlipot and committed by
Arnaldo Carvalho de Melo
2c15f5eb 568850ea

+46 -16
+33 -2
tools/perf/util/scripting-engines/trace-event-python.c
··· 682 682 struct tables *tables = container_of(dbe, struct tables, dbe); 683 683 PyObject *t; 684 684 685 - t = tuple_new(21); 685 + t = tuple_new(22); 686 686 687 687 tuple_set_u64(t, 0, es->db_id); 688 688 tuple_set_u64(t, 1, es->evsel->db_id); ··· 705 705 tuple_set_u64(t, 18, es->sample->data_src); 706 706 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); 707 707 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); 708 + tuple_set_u64(t, 21, es->call_path_id); 708 709 709 710 call_object(tables->sample_handler, t, "sample_table"); 710 711 ··· 1000 999 { 1001 1000 const char *perf_db_export_mode = "perf_db_export_mode"; 1002 1001 const char *perf_db_export_calls = "perf_db_export_calls"; 1003 - PyObject *db_export_mode, *db_export_calls; 1002 + const char *perf_db_export_callchains = "perf_db_export_callchains"; 1003 + PyObject *db_export_mode, *db_export_calls, *db_export_callchains; 1004 1004 bool export_calls = false; 1005 + bool export_callchains = false; 1005 1006 int ret; 1006 1007 1007 1008 memset(tables, 0, sizeof(struct tables)); ··· 1020 1017 if (!ret) 1021 1018 return; 1022 1019 1020 + /* handle export calls */ 1023 1021 tables->dbe.crp = NULL; 1024 1022 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); 1025 1023 if (db_export_calls) { ··· 1035 1031 call_return_processor__new(python_process_call_return, 1036 1032 &tables->dbe); 1037 1033 if (!tables->dbe.crp) 1034 + Py_FatalError("failed to create calls processor"); 1035 + } 1036 + 1037 + /* handle export callchains */ 1038 + tables->dbe.cpr = NULL; 1039 + db_export_callchains = PyDict_GetItemString(main_dict, 1040 + perf_db_export_callchains); 1041 + if (db_export_callchains) { 1042 + ret = PyObject_IsTrue(db_export_callchains); 1043 + if (ret == -1) 1044 + handler_call_die(perf_db_export_callchains); 1045 + export_callchains = !!ret; 1046 + } 1047 + 1048 + if (export_callchains) { 1049 + /* 1050 + * Attempt to use the call path root from the call return 1051 + * processor, if the call return processor is in use. Otherwise, 1052 + * we allocate a new call path root. This prevents exporting 1053 + * duplicate call path ids when both are in use simultaniously. 1054 + */ 1055 + if (tables->dbe.crp) 1056 + tables->dbe.cpr = tables->dbe.crp->cpr; 1057 + else 1058 + tables->dbe.cpr = call_path_root__new(); 1059 + 1060 + if (!tables->dbe.cpr) 1038 1061 Py_FatalError("failed to create calls processor"); 1039 1062 } 1040 1063
-13
tools/perf/util/thread-stack.c
··· 25 25 #include "call-path.h" 26 26 #include "thread-stack.h" 27 27 28 - /** 29 - * struct call_return_processor - provides a call-back to consume call-return 30 - * information. 31 - * @cpr: call path root 32 - * @process: call-back that accepts call/return information 33 - * @data: anonymous data for call-back 34 - */ 35 - struct call_return_processor { 36 - struct call_path_root *cpr; 37 - int (*process)(struct call_return *cr, void *data); 38 - void *data; 39 - }; 40 - 41 28 #define STACK_GROWTH 2048 42 29 43 30 /**
+13 -1
tools/perf/util/thread-stack.h
··· 25 25 struct ip_callchain; 26 26 struct symbol; 27 27 struct dso; 28 - struct call_return_processor; 29 28 struct comm; 30 29 struct perf_sample; 31 30 struct addr_location; ··· 65 66 u64 return_ref; 66 67 u64 db_id; 67 68 u32 flags; 69 + }; 70 + 71 + /** 72 + * struct call_return_processor - provides a call-back to consume call-return 73 + * information. 74 + * @cpr: call path root 75 + * @process: call-back that accepts call/return information 76 + * @data: anonymous data for call-back 77 + */ 78 + struct call_return_processor { 79 + struct call_path_root *cpr; 80 + int (*process)(struct call_return *cr, void *data); 81 + void *data; 68 82 }; 69 83 70 84 int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,