aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorChris Phlipot <cphlipot0@gmail.com>2016-04-28 04:19:10 -0400
committerArnaldo Carvalho de Melo <acme@redhat.com>2016-05-06 12:00:54 -0400
commit2c15f5eb04e9e7e19a2c8be6b50c63a4c6062a44 (patch)
treeced09e79a64751dc2e92629b4974f928bff16ec8 /tools/perf
parent568850eaad8cdd3783c3347623dfcad4f043cf1c (diff)
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>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/scripting-engines/trace-event-python.c35
-rw-r--r--tools/perf/util/thread-stack.c13
-rw-r--r--tools/perf/util/thread-stack.h14
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 7bb859202249..091bce67844c 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,
682 struct tables *tables = container_of(dbe, struct tables, dbe); 682 struct tables *tables = container_of(dbe, struct tables, dbe);
683 PyObject *t; 683 PyObject *t;
684 684
685 t = tuple_new(21); 685 t = tuple_new(22);
686 686
687 tuple_set_u64(t, 0, es->db_id); 687 tuple_set_u64(t, 0, es->db_id);
688 tuple_set_u64(t, 1, es->evsel->db_id); 688 tuple_set_u64(t, 1, es->evsel->db_id);
@@ -705,6 +705,7 @@ static int python_export_sample(struct db_export *dbe,
705 tuple_set_u64(t, 18, es->sample->data_src); 705 tuple_set_u64(t, 18, es->sample->data_src);
706 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK); 706 tuple_set_s32(t, 19, es->sample->flags & PERF_BRANCH_MASK);
707 tuple_set_s32(t, 20, !!(es->sample->flags & PERF_IP_FLAG_IN_TX)); 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 call_object(tables->sample_handler, t, "sample_table"); 710 call_object(tables->sample_handler, t, "sample_table");
710 711
@@ -999,8 +1000,10 @@ static void set_table_handlers(struct tables *tables)
999{ 1000{
1000 const char *perf_db_export_mode = "perf_db_export_mode"; 1001 const char *perf_db_export_mode = "perf_db_export_mode";
1001 const char *perf_db_export_calls = "perf_db_export_calls"; 1002 const char *perf_db_export_calls = "perf_db_export_calls";
1002 PyObject *db_export_mode, *db_export_calls; 1003 const char *perf_db_export_callchains = "perf_db_export_callchains";
1004 PyObject *db_export_mode, *db_export_calls, *db_export_callchains;
1003 bool export_calls = false; 1005 bool export_calls = false;
1006 bool export_callchains = false;
1004 int ret; 1007 int ret;
1005 1008
1006 memset(tables, 0, sizeof(struct tables)); 1009 memset(tables, 0, sizeof(struct tables));
@@ -1017,6 +1020,7 @@ static void set_table_handlers(struct tables *tables)
1017 if (!ret) 1020 if (!ret)
1018 return; 1021 return;
1019 1022
1023 /* handle export calls */
1020 tables->dbe.crp = NULL; 1024 tables->dbe.crp = NULL;
1021 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls); 1025 db_export_calls = PyDict_GetItemString(main_dict, perf_db_export_calls);
1022 if (db_export_calls) { 1026 if (db_export_calls) {
@@ -1034,6 +1038,33 @@ static void set_table_handlers(struct tables *tables)
1034 Py_FatalError("failed to create calls processor"); 1038 Py_FatalError("failed to create calls processor");
1035 } 1039 }
1036 1040
1041 /* handle export callchains */
1042 tables->dbe.cpr = NULL;
1043 db_export_callchains = PyDict_GetItemString(main_dict,
1044 perf_db_export_callchains);
1045 if (db_export_callchains) {
1046 ret = PyObject_IsTrue(db_export_callchains);
1047 if (ret == -1)
1048 handler_call_die(perf_db_export_callchains);
1049 export_callchains = !!ret;
1050 }
1051
1052 if (export_callchains) {
1053 /*
1054 * Attempt to use the call path root from the call return
1055 * processor, if the call return processor is in use. Otherwise,
1056 * we allocate a new call path root. This prevents exporting
1057 * duplicate call path ids when both are in use simultaniously.
1058 */
1059 if (tables->dbe.crp)
1060 tables->dbe.cpr = tables->dbe.crp->cpr;
1061 else
1062 tables->dbe.cpr = call_path_root__new();
1063
1064 if (!tables->dbe.cpr)
1065 Py_FatalError("failed to create calls processor");
1066 }
1067
1037 tables->db_export_mode = true; 1068 tables->db_export_mode = true;
1038 /* 1069 /*
1039 * Reserve per symbol space for symbol->db_id via symbol__priv() 1070 * 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 fc419a59c88b..825086aa9a08 100644
--- a/tools/perf/util/thread-stack.c
+++ b/tools/perf/util/thread-stack.c
@@ -25,19 +25,6 @@
25#include "call-path.h" 25#include "call-path.h"
26#include "thread-stack.h" 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 */
35struct call_return_processor {
36 struct call_path_root *cpr;
37 int (*process)(struct call_return *cr, void *data);
38 void *data;
39};
40
41#define STACK_GROWTH 2048 28#define STACK_GROWTH 2048
42 29
43/** 30/**
diff --git a/tools/perf/util/thread-stack.h b/tools/perf/util/thread-stack.h
index ec9beddfdbab..ad44c7944b8e 100644
--- a/tools/perf/util/thread-stack.h
+++ b/tools/perf/util/thread-stack.h
@@ -25,7 +25,6 @@ struct comm;
25struct ip_callchain; 25struct ip_callchain;
26struct symbol; 26struct symbol;
27struct dso; 27struct dso;
28struct call_return_processor;
29struct comm; 28struct comm;
30struct perf_sample; 29struct perf_sample;
31struct addr_location; 30struct addr_location;
@@ -68,6 +67,19 @@ struct call_return {
68 u32 flags; 67 u32 flags;
69}; 68};
70 69
70/**
71 * struct call_return_processor - provides a call-back to consume call-return
72 * information.
73 * @cpr: call path root
74 * @process: call-back that accepts call/return information
75 * @data: anonymous data for call-back
76 */
77struct call_return_processor {
78 struct call_path_root *cpr;
79 int (*process)(struct call_return *cr, void *data);
80 void *data;
81};
82
71int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip, 83int thread_stack__event(struct thread *thread, u32 flags, u64 from_ip,
72 u64 to_ip, u16 insn_len, u64 trace_nr); 84 u64 to_ip, u16 insn_len, u64 trace_nr);
73void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr); 85void thread_stack__set_trace_nr(struct thread *thread, u64 trace_nr);