aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorJohn Kacur <jkacur@redhat.com>2009-09-28 09:32:55 -0400
committerIngo Molnar <mingo@elte.hu>2009-09-30 07:57:56 -0400
commit3d1d07ecd2009f65cb2091563fa21f9600c36774 (patch)
treea1ef97a8264fc880ee8a9406a9be9070d0d12176 /tools/perf
parentdd68ada2d417e57b848822a1407b5317a54136c5 (diff)
perf tools: Put common histogram functions in their own file
Move histogram related functions into their own files (hist.c and hist.h) and make use of them in builtin-annotate.c and builtin-report.c. Signed-off-by: John Kacur <jkacur@redhat.com> Acked-by: Frederic Weisbecker <fweisbec@gmail.com> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <alpine.LFD.2.00.0909281531180.8316@localhost.localdomain> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile2
-rw-r--r--tools/perf/builtin-annotate.c152
-rw-r--r--tools/perf/builtin-report.c164
-rw-r--r--tools/perf/util/hist.c164
-rw-r--r--tools/perf/util/hist.h47
5 files changed, 216 insertions, 313 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 0a9e5aede318..3a99a9fda645 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -340,6 +340,7 @@ LIB_H += util/module.h
340LIB_H += util/color.h 340LIB_H += util/color.h
341LIB_H += util/values.h 341LIB_H += util/values.h
342LIB_H += util/sort.h 342LIB_H += util/sort.h
343LIB_H += util/hist.h
343 344
344LIB_OBJS += util/abspath.o 345LIB_OBJS += util/abspath.o
345LIB_OBJS += util/alias.o 346LIB_OBJS += util/alias.o
@@ -376,6 +377,7 @@ LIB_OBJS += util/trace-event-read.o
376LIB_OBJS += util/trace-event-info.o 377LIB_OBJS += util/trace-event-info.o
377LIB_OBJS += util/svghelper.o 378LIB_OBJS += util/svghelper.o
378LIB_OBJS += util/sort.o 379LIB_OBJS += util/sort.o
380LIB_OBJS += util/hist.o
379 381
380BUILTIN_OBJS += builtin-annotate.o 382BUILTIN_OBJS += builtin-annotate.o
381BUILTIN_OBJS += builtin-help.o 383BUILTIN_OBJS += builtin-help.o
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 059c565b31ea..df516dce9540 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -23,6 +23,7 @@
23#include "util/parse-events.h" 23#include "util/parse-events.h"
24#include "util/thread.h" 24#include "util/thread.h"
25#include "util/sort.h" 25#include "util/sort.h"
26#include "util/hist.h"
26 27
27static char const *input_name = "perf.data"; 28static char const *input_name = "perf.data";
28 29
@@ -47,45 +48,6 @@ struct sym_ext {
47 char *path; 48 char *path;
48}; 49};
49 50
50/*
51 * histogram, sorted on item, collects counts
52 */
53
54static struct rb_root hist;
55
56static int64_t
57hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
58{
59 struct sort_entry *se;
60 int64_t cmp = 0;
61
62 list_for_each_entry(se, &hist_entry__sort_list, list) {
63 cmp = se->cmp(left, right);
64 if (cmp)
65 break;
66 }
67
68 return cmp;
69}
70
71static int64_t
72hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
73{
74 struct sort_entry *se;
75 int64_t cmp = 0;
76
77 list_for_each_entry(se, &hist_entry__sort_list, list) {
78 int64_t (*f)(struct hist_entry *, struct hist_entry *);
79
80 f = se->collapse ?: se->cmp;
81
82 cmp = f(left, right);
83 if (cmp)
84 break;
85 }
86
87 return cmp;
88}
89 51
90/* 52/*
91 * collect histogram counts 53 * collect histogram counts
@@ -163,116 +125,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
163 return 0; 125 return 0;
164} 126}
165 127
166static void hist_entry__free(struct hist_entry *he)
167{
168 free(he);
169}
170
171/*
172 * collapse the histogram
173 */
174
175static struct rb_root collapse_hists;
176
177static void collapse__insert_entry(struct hist_entry *he)
178{
179 struct rb_node **p = &collapse_hists.rb_node;
180 struct rb_node *parent = NULL;
181 struct hist_entry *iter;
182 int64_t cmp;
183
184 while (*p != NULL) {
185 parent = *p;
186 iter = rb_entry(parent, struct hist_entry, rb_node);
187
188 cmp = hist_entry__collapse(iter, he);
189
190 if (!cmp) {
191 iter->count += he->count;
192 hist_entry__free(he);
193 return;
194 }
195
196 if (cmp < 0)
197 p = &(*p)->rb_left;
198 else
199 p = &(*p)->rb_right;
200 }
201
202 rb_link_node(&he->rb_node, parent, p);
203 rb_insert_color(&he->rb_node, &collapse_hists);
204}
205
206static void collapse__resort(void)
207{
208 struct rb_node *next;
209 struct hist_entry *n;
210
211 if (!sort__need_collapse)
212 return;
213
214 next = rb_first(&hist);
215 while (next) {
216 n = rb_entry(next, struct hist_entry, rb_node);
217 next = rb_next(&n->rb_node);
218
219 rb_erase(&n->rb_node, &hist);
220 collapse__insert_entry(n);
221 }
222}
223
224/*
225 * reverse the map, sort on count.
226 */
227
228static struct rb_root output_hists;
229
230static void output__insert_entry(struct hist_entry *he)
231{
232 struct rb_node **p = &output_hists.rb_node;
233 struct rb_node *parent = NULL;
234 struct hist_entry *iter;
235
236 while (*p != NULL) {
237 parent = *p;
238 iter = rb_entry(parent, struct hist_entry, rb_node);
239
240 if (he->count > iter->count)
241 p = &(*p)->rb_left;
242 else
243 p = &(*p)->rb_right;
244 }
245
246 rb_link_node(&he->rb_node, parent, p);
247 rb_insert_color(&he->rb_node, &output_hists);
248}
249
250static void output__resort(void)
251{
252 struct rb_node *next;
253 struct hist_entry *n;
254 struct rb_root *tree = &hist;
255
256 if (sort__need_collapse)
257 tree = &collapse_hists;
258
259 next = rb_first(tree);
260
261 while (next) {
262 n = rb_entry(next, struct hist_entry, rb_node);
263 next = rb_next(&n->rb_node);
264
265 rb_erase(&n->rb_node, tree);
266 output__insert_entry(n);
267 }
268}
269
270static unsigned long total = 0,
271 total_mmap = 0,
272 total_comm = 0,
273 total_fork = 0,
274 total_unknown = 0;
275
276static int 128static int
277process_sample_event(event_t *event, unsigned long offset, unsigned long head) 129process_sample_event(event_t *event, unsigned long offset, unsigned long head)
278{ 130{
@@ -861,7 +713,7 @@ more:
861 dsos__fprintf(stdout); 713 dsos__fprintf(stdout);
862 714
863 collapse__resort(); 715 collapse__resort();
864 output__resort(); 716 output__resort(total);
865 717
866 find_annotations(); 718 find_annotations();
867 719
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 7b43504900ff..c1a54fc8527a 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -28,6 +28,7 @@
28 28
29#include "util/thread.h" 29#include "util/thread.h"
30#include "util/sort.h" 30#include "util/sort.h"
31#include "util/hist.h"
31 32
32static char const *input_name = "perf.data"; 33static char const *input_name = "perf.data";
33 34
@@ -55,8 +56,6 @@ static int exclude_other = 1;
55 56
56static char callchain_default_opt[] = "fractal,0.5"; 57static char callchain_default_opt[] = "fractal,0.5";
57 58
58static int callchain;
59
60static char __cwd[PATH_MAX]; 59static char __cwd[PATH_MAX];
61static char *cwd = __cwd; 60static char *cwd = __cwd;
62static int cwdlen; 61static int cwdlen;
@@ -66,50 +65,8 @@ static struct thread *last_match;
66 65
67static struct perf_header *header; 66static struct perf_header *header;
68 67
69static
70struct callchain_param callchain_param = {
71 .mode = CHAIN_GRAPH_REL,
72 .min_percent = 0.5
73};
74
75static u64 sample_type; 68static u64 sample_type;
76 69
77static struct rb_root hist;
78
79static int64_t
80hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
81{
82 struct sort_entry *se;
83 int64_t cmp = 0;
84
85 list_for_each_entry(se, &hist_entry__sort_list, list) {
86 cmp = se->cmp(left, right);
87 if (cmp)
88 break;
89 }
90
91 return cmp;
92}
93
94static int64_t
95hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
96{
97 struct sort_entry *se;
98 int64_t cmp = 0;
99
100 list_for_each_entry(se, &hist_entry__sort_list, list) {
101 int64_t (*f)(struct hist_entry *, struct hist_entry *);
102
103 f = se->collapse ?: se->cmp;
104
105 cmp = f(left, right);
106 if (cmp)
107 break;
108 }
109
110 return cmp;
111}
112
113static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask) 70static size_t ipchain__fprintf_graph_line(FILE *fp, int depth, int depth_mask)
114{ 71{
115 int i; 72 int i;
@@ -308,7 +265,6 @@ hist_entry_callchain__fprintf(FILE *fp, struct hist_entry *self,
308 return ret; 265 return ret;
309} 266}
310 267
311
312static size_t 268static size_t
313hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples) 269hist_entry__fprintf(FILE *fp, struct hist_entry *self, u64 total_samples)
314{ 270{
@@ -573,117 +529,6 @@ hist_entry__add(struct thread *thread, struct map *map, struct dso *dso,
573 return 0; 529 return 0;
574} 530}
575 531
576static void hist_entry__free(struct hist_entry *he)
577{
578 free(he);
579}
580
581/*
582 * collapse the histogram
583 */
584
585static struct rb_root collapse_hists;
586
587static void collapse__insert_entry(struct hist_entry *he)
588{
589 struct rb_node **p = &collapse_hists.rb_node;
590 struct rb_node *parent = NULL;
591 struct hist_entry *iter;
592 int64_t cmp;
593
594 while (*p != NULL) {
595 parent = *p;
596 iter = rb_entry(parent, struct hist_entry, rb_node);
597
598 cmp = hist_entry__collapse(iter, he);
599
600 if (!cmp) {
601 iter->count += he->count;
602 hist_entry__free(he);
603 return;
604 }
605
606 if (cmp < 0)
607 p = &(*p)->rb_left;
608 else
609 p = &(*p)->rb_right;
610 }
611
612 rb_link_node(&he->rb_node, parent, p);
613 rb_insert_color(&he->rb_node, &collapse_hists);
614}
615
616static void collapse__resort(void)
617{
618 struct rb_node *next;
619 struct hist_entry *n;
620
621 if (!sort__need_collapse)
622 return;
623
624 next = rb_first(&hist);
625 while (next) {
626 n = rb_entry(next, struct hist_entry, rb_node);
627 next = rb_next(&n->rb_node);
628
629 rb_erase(&n->rb_node, &hist);
630 collapse__insert_entry(n);
631 }
632}
633
634/*
635 * reverse the map, sort on count.
636 */
637
638static struct rb_root output_hists;
639
640static void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
641{
642 struct rb_node **p = &output_hists.rb_node;
643 struct rb_node *parent = NULL;
644 struct hist_entry *iter;
645
646 if (callchain)
647 callchain_param.sort(&he->sorted_chain, &he->callchain,
648 min_callchain_hits, &callchain_param);
649
650 while (*p != NULL) {
651 parent = *p;
652 iter = rb_entry(parent, struct hist_entry, rb_node);
653
654 if (he->count > iter->count)
655 p = &(*p)->rb_left;
656 else
657 p = &(*p)->rb_right;
658 }
659
660 rb_link_node(&he->rb_node, parent, p);
661 rb_insert_color(&he->rb_node, &output_hists);
662}
663
664static void output__resort(u64 total_samples)
665{
666 struct rb_node *next;
667 struct hist_entry *n;
668 struct rb_root *tree = &hist;
669 u64 min_callchain_hits;
670
671 min_callchain_hits = total_samples * (callchain_param.min_percent / 100);
672
673 if (sort__need_collapse)
674 tree = &collapse_hists;
675
676 next = rb_first(tree);
677
678 while (next) {
679 n = rb_entry(next, struct hist_entry, rb_node);
680 next = rb_next(&n->rb_node);
681
682 rb_erase(&n->rb_node, tree);
683 output__insert_entry(n, min_callchain_hits);
684 }
685}
686
687static size_t output__fprintf(FILE *fp, u64 total_samples) 532static size_t output__fprintf(FILE *fp, u64 total_samples)
688{ 533{
689 struct hist_entry *pos; 534 struct hist_entry *pos;
@@ -778,13 +623,6 @@ print_entries:
778 return ret; 623 return ret;
779} 624}
780 625
781static unsigned long total = 0,
782 total_mmap = 0,
783 total_comm = 0,
784 total_fork = 0,
785 total_unknown = 0,
786 total_lost = 0;
787
788static int validate_chain(struct ip_callchain *chain, event_t *event) 626static int validate_chain(struct ip_callchain *chain, event_t *event)
789{ 627{
790 unsigned int chain_size; 628 unsigned int chain_size;
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
new file mode 100644
index 000000000000..82808dc4f8e3
--- /dev/null
+++ b/tools/perf/util/hist.c
@@ -0,0 +1,164 @@
1#include "hist.h"
2
3struct rb_root hist;
4struct rb_root collapse_hists;
5struct rb_root output_hists;
6int callchain;
7
8struct callchain_param callchain_param = {
9 .mode = CHAIN_GRAPH_REL,
10 .min_percent = 0.5
11};
12
13unsigned long total;
14unsigned long total_mmap;
15unsigned long total_comm;
16unsigned long total_fork;
17unsigned long total_unknown;
18unsigned long total_lost;
19
20/*
21 * histogram, sorted on item, collects counts
22 */
23
24int64_t
25hist_entry__cmp(struct hist_entry *left, struct hist_entry *right)
26{
27 struct sort_entry *se;
28 int64_t cmp = 0;
29
30 list_for_each_entry(se, &hist_entry__sort_list, list) {
31 cmp = se->cmp(left, right);
32 if (cmp)
33 break;
34 }
35
36 return cmp;
37}
38
39int64_t
40hist_entry__collapse(struct hist_entry *left, struct hist_entry *right)
41{
42 struct sort_entry *se;
43 int64_t cmp = 0;
44
45 list_for_each_entry(se, &hist_entry__sort_list, list) {
46 int64_t (*f)(struct hist_entry *, struct hist_entry *);
47
48 f = se->collapse ?: se->cmp;
49
50 cmp = f(left, right);
51 if (cmp)
52 break;
53 }
54
55 return cmp;
56}
57
58void hist_entry__free(struct hist_entry *he)
59{
60 free(he);
61}
62
63/*
64 * collapse the histogram
65 */
66
67void collapse__insert_entry(struct hist_entry *he)
68{
69 struct rb_node **p = &collapse_hists.rb_node;
70 struct rb_node *parent = NULL;
71 struct hist_entry *iter;
72 int64_t cmp;
73
74 while (*p != NULL) {
75 parent = *p;
76 iter = rb_entry(parent, struct hist_entry, rb_node);
77
78 cmp = hist_entry__collapse(iter, he);
79
80 if (!cmp) {
81 iter->count += he->count;
82 hist_entry__free(he);
83 return;
84 }
85
86 if (cmp < 0)
87 p = &(*p)->rb_left;
88 else
89 p = &(*p)->rb_right;
90 }
91
92 rb_link_node(&he->rb_node, parent, p);
93 rb_insert_color(&he->rb_node, &collapse_hists);
94}
95
96void collapse__resort(void)
97{
98 struct rb_node *next;
99 struct hist_entry *n;
100
101 if (!sort__need_collapse)
102 return;
103
104 next = rb_first(&hist);
105 while (next) {
106 n = rb_entry(next, struct hist_entry, rb_node);
107 next = rb_next(&n->rb_node);
108
109 rb_erase(&n->rb_node, &hist);
110 collapse__insert_entry(n);
111 }
112}
113
114/*
115 * reverse the map, sort on count.
116 */
117
118void output__insert_entry(struct hist_entry *he, u64 min_callchain_hits)
119{
120 struct rb_node **p = &output_hists.rb_node;
121 struct rb_node *parent = NULL;
122 struct hist_entry *iter;
123
124 if (callchain)
125 callchain_param.sort(&he->sorted_chain, &he->callchain,
126 min_callchain_hits, &callchain_param);
127
128 while (*p != NULL) {
129 parent = *p;
130 iter = rb_entry(parent, struct hist_entry, rb_node);
131
132 if (he->count > iter->count)
133 p = &(*p)->rb_left;
134 else
135 p = &(*p)->rb_right;
136 }
137
138 rb_link_node(&he->rb_node, parent, p);
139 rb_insert_color(&he->rb_node, &output_hists);
140}
141
142void output__resort(u64 total_samples)
143{
144 struct rb_node *next;
145 struct hist_entry *n;
146 struct rb_root *tree = &hist;
147 u64 min_callchain_hits;
148
149 min_callchain_hits =
150 total_samples * (callchain_param.min_percent / 100);
151
152 if (sort__need_collapse)
153 tree = &collapse_hists;
154
155 next = rb_first(tree);
156
157 while (next) {
158 n = rb_entry(next, struct hist_entry, rb_node);
159 next = rb_next(&n->rb_node);
160
161 rb_erase(&n->rb_node, tree);
162 output__insert_entry(n, min_callchain_hits);
163 }
164}
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
new file mode 100644
index 000000000000..9a8daa12b43a
--- /dev/null
+++ b/tools/perf/util/hist.h
@@ -0,0 +1,47 @@
1#ifndef __PERF_HIST_H
2#define __PERF_HIST_H
3#include "../builtin.h"
4
5#include "util.h"
6
7#include "color.h"
8#include <linux/list.h>
9#include "cache.h"
10#include <linux/rbtree.h>
11#include "symbol.h"
12#include "string.h"
13#include "callchain.h"
14#include "strlist.h"
15#include "values.h"
16
17#include "../perf.h"
18#include "debug.h"
19#include "header.h"
20
21#include "parse-options.h"
22#include "parse-events.h"
23
24#include "thread.h"
25#include "sort.h"
26
27extern struct rb_root hist;
28extern struct rb_root collapse_hists;
29extern struct rb_root output_hists;
30extern int callchain;
31extern struct callchain_param callchain_param;
32extern unsigned long total;
33extern unsigned long total_mmap;
34extern unsigned long total_comm;
35extern unsigned long total_fork;
36extern unsigned long total_unknown;
37extern unsigned long total_lost;
38
39extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
40extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
41extern void hist_entry__free(struct hist_entry *);
42extern void collapse__insert_entry(struct hist_entry *);
43extern void collapse__resort(void);
44extern void output__insert_entry(struct hist_entry *, u64);
45extern void output__resort(u64);
46
47#endif /* __PERF_HIST_H */