diff options
author | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-10-25 12:42:45 -0400 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2012-11-08 15:43:09 -0500 |
commit | b821c7325354c589ccc9611cf9e6b0d7490ed6a6 (patch) | |
tree | 103deb4210a3187c52597def760435502cdc907e /tools | |
parent | ff6f7778a66edc033044a6baa2459ce79519e571 (diff) |
perf diff: Start moving to support matching more than two hists
We want to match more than two hists, so that we can match more than two
perf.data files and moreover, match hist_entries (buckets) in multiple
events in a group.
So the "baseline"/"leader" will instead of a ->pair pointer, use a
list_head, that will link to the pairs and hists__match use it.
Following that perf_evlist__link will link the hists in its evsel
groups.
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-2kbmzepoi544ygj9godseqpv@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/perf/builtin-diff.c | 21 | ||||
-rw-r--r-- | tools/perf/ui/hist.c | 10 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 2 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 27 |
4 files changed, 42 insertions, 18 deletions
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index 380683de1df3..8a9db38e562f 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -154,7 +154,7 @@ static double get_period_percent(struct hist_entry *he, u64 period) | |||
154 | 154 | ||
155 | double perf_diff__compute_delta(struct hist_entry *he) | 155 | double perf_diff__compute_delta(struct hist_entry *he) |
156 | { | 156 | { |
157 | struct hist_entry *pair = he->pair; | 157 | struct hist_entry *pair = hist_entry__next_pair(he); |
158 | double new_percent = get_period_percent(he, he->stat.period); | 158 | double new_percent = get_period_percent(he, he->stat.period); |
159 | double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0; | 159 | double old_percent = pair ? get_period_percent(pair, pair->stat.period) : 0.0; |
160 | 160 | ||
@@ -165,7 +165,7 @@ double perf_diff__compute_delta(struct hist_entry *he) | |||
165 | 165 | ||
166 | double perf_diff__compute_ratio(struct hist_entry *he) | 166 | double perf_diff__compute_ratio(struct hist_entry *he) |
167 | { | 167 | { |
168 | struct hist_entry *pair = he->pair; | 168 | struct hist_entry *pair = hist_entry__next_pair(he); |
169 | double new_period = he->stat.period; | 169 | double new_period = he->stat.period; |
170 | double old_period = pair ? pair->stat.period : 0; | 170 | double old_period = pair ? pair->stat.period : 0; |
171 | 171 | ||
@@ -176,7 +176,7 @@ double perf_diff__compute_ratio(struct hist_entry *he) | |||
176 | 176 | ||
177 | s64 perf_diff__compute_wdiff(struct hist_entry *he) | 177 | s64 perf_diff__compute_wdiff(struct hist_entry *he) |
178 | { | 178 | { |
179 | struct hist_entry *pair = he->pair; | 179 | struct hist_entry *pair = hist_entry__next_pair(he); |
180 | u64 new_period = he->stat.period; | 180 | u64 new_period = he->stat.period; |
181 | u64 old_period = pair ? pair->stat.period : 0; | 181 | u64 old_period = pair ? pair->stat.period : 0; |
182 | 182 | ||
@@ -193,7 +193,7 @@ s64 perf_diff__compute_wdiff(struct hist_entry *he) | |||
193 | 193 | ||
194 | static int formula_delta(struct hist_entry *he, char *buf, size_t size) | 194 | static int formula_delta(struct hist_entry *he, char *buf, size_t size) |
195 | { | 195 | { |
196 | struct hist_entry *pair = he->pair; | 196 | struct hist_entry *pair = hist_entry__next_pair(he); |
197 | 197 | ||
198 | if (!pair) | 198 | if (!pair) |
199 | return -1; | 199 | return -1; |
@@ -207,7 +207,7 @@ static int formula_delta(struct hist_entry *he, char *buf, size_t size) | |||
207 | 207 | ||
208 | static int formula_ratio(struct hist_entry *he, char *buf, size_t size) | 208 | static int formula_ratio(struct hist_entry *he, char *buf, size_t size) |
209 | { | 209 | { |
210 | struct hist_entry *pair = he->pair; | 210 | struct hist_entry *pair = hist_entry__next_pair(he); |
211 | double new_period = he->stat.period; | 211 | double new_period = he->stat.period; |
212 | double old_period = pair ? pair->stat.period : 0; | 212 | double old_period = pair ? pair->stat.period : 0; |
213 | 213 | ||
@@ -219,7 +219,7 @@ static int formula_ratio(struct hist_entry *he, char *buf, size_t size) | |||
219 | 219 | ||
220 | static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) | 220 | static int formula_wdiff(struct hist_entry *he, char *buf, size_t size) |
221 | { | 221 | { |
222 | struct hist_entry *pair = he->pair; | 222 | struct hist_entry *pair = hist_entry__next_pair(he); |
223 | u64 new_period = he->stat.period; | 223 | u64 new_period = he->stat.period; |
224 | u64 old_period = pair ? pair->stat.period : 0; | 224 | u64 old_period = pair ? pair->stat.period : 0; |
225 | 225 | ||
@@ -359,8 +359,11 @@ static void hists__match(struct hists *older, struct hists *newer) | |||
359 | struct rb_node *nd; | 359 | struct rb_node *nd; |
360 | 360 | ||
361 | for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) { | 361 | for (nd = rb_first(&newer->entries); nd; nd = rb_next(nd)) { |
362 | struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node); | 362 | struct hist_entry *pos = rb_entry(nd, struct hist_entry, rb_node), |
363 | pos->pair = hists__find_entry(older, pos); | 363 | *pair = hists__find_entry(older, pos); |
364 | |||
365 | if (pair) | ||
366 | hist__entry_add_pair(pos, pair); | ||
364 | } | 367 | } |
365 | } | 368 | } |
366 | 369 | ||
@@ -402,7 +405,7 @@ static void hists__baseline_only(struct hists *hists) | |||
402 | struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); | 405 | struct hist_entry *he = rb_entry(next, struct hist_entry, rb_node); |
403 | 406 | ||
404 | next = rb_next(&he->rb_node); | 407 | next = rb_next(&he->rb_node); |
405 | if (!he->pair) { | 408 | if (!hist_entry__next_pair(he)) { |
406 | rb_erase(&he->rb_node, &hists->entries); | 409 | rb_erase(&he->rb_node, &hists->entries); |
407 | hist_entry__free(he); | 410 | hist_entry__free(he); |
408 | } | 411 | } |
diff --git a/tools/perf/ui/hist.c b/tools/perf/ui/hist.c index 4f5f4756faac..aa84130024d5 100644 --- a/tools/perf/ui/hist.c +++ b/tools/perf/ui/hist.c | |||
@@ -161,7 +161,7 @@ static int hpp__width_baseline(struct perf_hpp *hpp __maybe_unused) | |||
161 | 161 | ||
162 | static double baseline_percent(struct hist_entry *he) | 162 | static double baseline_percent(struct hist_entry *he) |
163 | { | 163 | { |
164 | struct hist_entry *pair = he->pair; | 164 | struct hist_entry *pair = hist_entry__next_pair(he); |
165 | struct hists *pair_hists = pair ? pair->hists : NULL; | 165 | struct hists *pair_hists = pair ? pair->hists : NULL; |
166 | double percent = 0.0; | 166 | double percent = 0.0; |
167 | 167 | ||
@@ -179,7 +179,7 @@ static int hpp__color_baseline(struct perf_hpp *hpp, struct hist_entry *he) | |||
179 | { | 179 | { |
180 | double percent = baseline_percent(he); | 180 | double percent = baseline_percent(he); |
181 | 181 | ||
182 | if (he->pair) | 182 | if (hist_entry__has_pairs(he)) |
183 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); | 183 | return percent_color_snprintf(hpp->buf, hpp->size, " %6.2f%%", percent); |
184 | else | 184 | else |
185 | return scnprintf(hpp->buf, hpp->size, " "); | 185 | return scnprintf(hpp->buf, hpp->size, " "); |
@@ -190,7 +190,7 @@ static int hpp__entry_baseline(struct perf_hpp *hpp, struct hist_entry *he) | |||
190 | double percent = baseline_percent(he); | 190 | double percent = baseline_percent(he); |
191 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; | 191 | const char *fmt = symbol_conf.field_sep ? "%.2f" : " %6.2f%%"; |
192 | 192 | ||
193 | if (he->pair || symbol_conf.field_sep) | 193 | if (hist_entry__has_pairs(he) || symbol_conf.field_sep) |
194 | return scnprintf(hpp->buf, hpp->size, fmt, percent); | 194 | return scnprintf(hpp->buf, hpp->size, fmt, percent); |
195 | else | 195 | else |
196 | return scnprintf(hpp->buf, hpp->size, " "); | 196 | return scnprintf(hpp->buf, hpp->size, " "); |
@@ -248,7 +248,7 @@ static int hpp__width_period_baseline(struct perf_hpp *hpp __maybe_unused) | |||
248 | 248 | ||
249 | static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) | 249 | static int hpp__entry_period_baseline(struct perf_hpp *hpp, struct hist_entry *he) |
250 | { | 250 | { |
251 | struct hist_entry *pair = he->pair; | 251 | struct hist_entry *pair = hist_entry__next_pair(he); |
252 | u64 period = pair ? pair->stat.period : 0; | 252 | u64 period = pair ? pair->stat.period : 0; |
253 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; | 253 | const char *fmt = symbol_conf.field_sep ? "%" PRIu64 : "%12" PRIu64; |
254 | 254 | ||
@@ -354,7 +354,7 @@ static int hpp__width_displ(struct perf_hpp *hpp __maybe_unused) | |||
354 | static int hpp__entry_displ(struct perf_hpp *hpp, | 354 | static int hpp__entry_displ(struct perf_hpp *hpp, |
355 | struct hist_entry *he) | 355 | struct hist_entry *he) |
356 | { | 356 | { |
357 | struct hist_entry *pair = he->pair; | 357 | struct hist_entry *pair = hist_entry__next_pair(he); |
358 | long displacement = pair ? pair->position - he->position : 0; | 358 | long displacement = pair ? pair->position - he->position : 0; |
359 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; | 359 | const char *fmt = symbol_conf.field_sep ? "%s" : "%6.6s"; |
360 | char buf[32] = " "; | 360 | char buf[32] = " "; |
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index a1b823f8c17f..f42de79d2e6b 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -244,6 +244,8 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template) | |||
244 | he->ms.map->referenced = true; | 244 | he->ms.map->referenced = true; |
245 | if (symbol_conf.use_callchain) | 245 | if (symbol_conf.use_callchain) |
246 | callchain_init(he->callchain); | 246 | callchain_init(he->callchain); |
247 | |||
248 | INIT_LIST_HEAD(&he->pairs.node); | ||
247 | } | 249 | } |
248 | 250 | ||
249 | return he; | 251 | return he; |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index 13761d83a5a0..b4e8c3ba559d 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -77,6 +77,10 @@ struct hist_entry_diff { | |||
77 | struct hist_entry { | 77 | struct hist_entry { |
78 | struct rb_node rb_node_in; | 78 | struct rb_node rb_node_in; |
79 | struct rb_node rb_node; | 79 | struct rb_node rb_node; |
80 | union { | ||
81 | struct list_head node; | ||
82 | struct list_head head; | ||
83 | } pairs; | ||
80 | struct he_stat stat; | 84 | struct he_stat stat; |
81 | struct map_symbol ms; | 85 | struct map_symbol ms; |
82 | struct thread *thread; | 86 | struct thread *thread; |
@@ -96,15 +100,30 @@ struct hist_entry { | |||
96 | char *srcline; | 100 | char *srcline; |
97 | struct symbol *parent; | 101 | struct symbol *parent; |
98 | unsigned long position; | 102 | unsigned long position; |
99 | union { | 103 | struct rb_root sorted_chain; |
100 | struct hist_entry *pair; | ||
101 | struct rb_root sorted_chain; | ||
102 | }; | ||
103 | struct branch_info *branch_info; | 104 | struct branch_info *branch_info; |
104 | struct hists *hists; | 105 | struct hists *hists; |
105 | struct callchain_root callchain[0]; | 106 | struct callchain_root callchain[0]; |
106 | }; | 107 | }; |
107 | 108 | ||
109 | static inline bool hist_entry__has_pairs(struct hist_entry *he) | ||
110 | { | ||
111 | return !list_empty(&he->pairs.node); | ||
112 | } | ||
113 | |||
114 | static inline struct hist_entry *hist_entry__next_pair(struct hist_entry *he) | ||
115 | { | ||
116 | if (hist_entry__has_pairs(he)) | ||
117 | return list_entry(he->pairs.node.next, struct hist_entry, pairs.node); | ||
118 | return NULL; | ||
119 | } | ||
120 | |||
121 | static inline void hist__entry_add_pair(struct hist_entry *he, | ||
122 | struct hist_entry *pair) | ||
123 | { | ||
124 | list_add_tail(&he->pairs.head, &pair->pairs.node); | ||
125 | } | ||
126 | |||
108 | enum sort_type { | 127 | enum sort_type { |
109 | SORT_PID, | 128 | SORT_PID, |
110 | SORT_COMM, | 129 | SORT_COMM, |