diff options
author | Ingo Molnar <mingo@kernel.org> | 2014-05-22 05:37:40 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2014-05-22 05:37:40 -0400 |
commit | e450f90e8c7d0bf70519223c1b848446ae63f313 (patch) | |
tree | 078bfe88e5c3fbe397c9ca0d4d8ab2e0ff63979d /tools/perf/tests | |
parent | 6480c56130ba073df84d57d61062ec4118b10bbe (diff) | |
parent | eca8183699964579ca8a0b8d116bd1f4da0136f7 (diff) |
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/jolsa/perf into perf/core
Pull perf/core improvements and fixes from Jiri Olsa:
* Android related fixes for pager and map dso resolving (Michael Lentine)
* Add -F option for specifying output fields (Namhyung Kim)
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools/perf/tests')
-rw-r--r-- | tools/perf/tests/builtin-test.c | 4 | ||||
-rw-r--r-- | tools/perf/tests/hists_common.c | 57 | ||||
-rw-r--r-- | tools/perf/tests/hists_common.h | 3 | ||||
-rw-r--r-- | tools/perf/tests/hists_filter.c | 38 | ||||
-rw-r--r-- | tools/perf/tests/hists_link.c | 30 | ||||
-rw-r--r-- | tools/perf/tests/hists_output.c | 618 | ||||
-rw-r--r-- | tools/perf/tests/tests.h | 1 |
7 files changed, 691 insertions, 60 deletions
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c index 5e0764b09317..831f52cae197 100644 --- a/tools/perf/tests/builtin-test.c +++ b/tools/perf/tests/builtin-test.c | |||
@@ -136,6 +136,10 @@ static struct test { | |||
136 | .func = test__thread_mg_share, | 136 | .func = test__thread_mg_share, |
137 | }, | 137 | }, |
138 | { | 138 | { |
139 | .desc = "Test output sorting of hist entries", | ||
140 | .func = test__hists_output, | ||
141 | }, | ||
142 | { | ||
139 | .func = NULL, | 143 | .func = NULL, |
140 | }, | 144 | }, |
141 | }; | 145 | }; |
diff --git a/tools/perf/tests/hists_common.c b/tools/perf/tests/hists_common.c index 44655b395bb9..e4e01aadc3be 100644 --- a/tools/perf/tests/hists_common.c +++ b/tools/perf/tests/hists_common.c | |||
@@ -146,3 +146,60 @@ out: | |||
146 | machine__delete(machine); | 146 | machine__delete(machine); |
147 | return NULL; | 147 | return NULL; |
148 | } | 148 | } |
149 | |||
150 | void print_hists_in(struct hists *hists) | ||
151 | { | ||
152 | int i = 0; | ||
153 | struct rb_root *root; | ||
154 | struct rb_node *node; | ||
155 | |||
156 | if (sort__need_collapse) | ||
157 | root = &hists->entries_collapsed; | ||
158 | else | ||
159 | root = hists->entries_in; | ||
160 | |||
161 | pr_info("----- %s --------\n", __func__); | ||
162 | node = rb_first(root); | ||
163 | while (node) { | ||
164 | struct hist_entry *he; | ||
165 | |||
166 | he = rb_entry(node, struct hist_entry, rb_node_in); | ||
167 | |||
168 | if (!he->filtered) { | ||
169 | pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", | ||
170 | i, thread__comm_str(he->thread), | ||
171 | he->ms.map->dso->short_name, | ||
172 | he->ms.sym->name, he->stat.period); | ||
173 | } | ||
174 | |||
175 | i++; | ||
176 | node = rb_next(node); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | void print_hists_out(struct hists *hists) | ||
181 | { | ||
182 | int i = 0; | ||
183 | struct rb_root *root; | ||
184 | struct rb_node *node; | ||
185 | |||
186 | root = &hists->entries; | ||
187 | |||
188 | pr_info("----- %s --------\n", __func__); | ||
189 | node = rb_first(root); | ||
190 | while (node) { | ||
191 | struct hist_entry *he; | ||
192 | |||
193 | he = rb_entry(node, struct hist_entry, rb_node); | ||
194 | |||
195 | if (!he->filtered) { | ||
196 | pr_info("%2d: entry: %8s:%5d [%-8s] %20s: period = %"PRIu64"\n", | ||
197 | i, thread__comm_str(he->thread), he->thread->tid, | ||
198 | he->ms.map->dso->short_name, | ||
199 | he->ms.sym->name, he->stat.period); | ||
200 | } | ||
201 | |||
202 | i++; | ||
203 | node = rb_next(node); | ||
204 | } | ||
205 | } | ||
diff --git a/tools/perf/tests/hists_common.h b/tools/perf/tests/hists_common.h index 2528b8fc105a..1415ae69d7b6 100644 --- a/tools/perf/tests/hists_common.h +++ b/tools/perf/tests/hists_common.h | |||
@@ -41,4 +41,7 @@ struct machines; | |||
41 | */ | 41 | */ |
42 | struct machine *setup_fake_machine(struct machines *machines); | 42 | struct machine *setup_fake_machine(struct machines *machines); |
43 | 43 | ||
44 | void print_hists_in(struct hists *hists); | ||
45 | void print_hists_out(struct hists *hists); | ||
46 | |||
44 | #endif /* __PERF_TESTS__HISTS_COMMON_H__ */ | 47 | #endif /* __PERF_TESTS__HISTS_COMMON_H__ */ |
diff --git a/tools/perf/tests/hists_filter.c b/tools/perf/tests/hists_filter.c index 4617a8bee29b..c5ba924a3581 100644 --- a/tools/perf/tests/hists_filter.c +++ b/tools/perf/tests/hists_filter.c | |||
@@ -98,33 +98,6 @@ out: | |||
98 | return TEST_FAIL; | 98 | return TEST_FAIL; |
99 | } | 99 | } |
100 | 100 | ||
101 | static void print_hists(struct hists *hists) | ||
102 | { | ||
103 | int i = 0; | ||
104 | struct rb_root *root; | ||
105 | struct rb_node *node; | ||
106 | |||
107 | root = &hists->entries; | ||
108 | |||
109 | pr_info("----- %s --------\n", __func__); | ||
110 | node = rb_first(root); | ||
111 | while (node) { | ||
112 | struct hist_entry *he; | ||
113 | |||
114 | he = rb_entry(node, struct hist_entry, rb_node); | ||
115 | |||
116 | if (!he->filtered) { | ||
117 | pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", | ||
118 | i, thread__comm_str(he->thread), | ||
119 | he->ms.map->dso->short_name, | ||
120 | he->ms.sym->name, he->stat.period); | ||
121 | } | ||
122 | |||
123 | i++; | ||
124 | node = rb_next(node); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | int test__hists_filter(void) | 101 | int test__hists_filter(void) |
129 | { | 102 | { |
130 | int err = TEST_FAIL; | 103 | int err = TEST_FAIL; |
@@ -169,7 +142,7 @@ int test__hists_filter(void) | |||
169 | 142 | ||
170 | if (verbose > 2) { | 143 | if (verbose > 2) { |
171 | pr_info("Normal histogram\n"); | 144 | pr_info("Normal histogram\n"); |
172 | print_hists(hists); | 145 | print_hists_out(hists); |
173 | } | 146 | } |
174 | 147 | ||
175 | TEST_ASSERT_VAL("Invalid nr samples", | 148 | TEST_ASSERT_VAL("Invalid nr samples", |
@@ -193,7 +166,7 @@ int test__hists_filter(void) | |||
193 | 166 | ||
194 | if (verbose > 2) { | 167 | if (verbose > 2) { |
195 | pr_info("Histogram for thread filter\n"); | 168 | pr_info("Histogram for thread filter\n"); |
196 | print_hists(hists); | 169 | print_hists_out(hists); |
197 | } | 170 | } |
198 | 171 | ||
199 | /* normal stats should be invariant */ | 172 | /* normal stats should be invariant */ |
@@ -222,7 +195,7 @@ int test__hists_filter(void) | |||
222 | 195 | ||
223 | if (verbose > 2) { | 196 | if (verbose > 2) { |
224 | pr_info("Histogram for dso filter\n"); | 197 | pr_info("Histogram for dso filter\n"); |
225 | print_hists(hists); | 198 | print_hists_out(hists); |
226 | } | 199 | } |
227 | 200 | ||
228 | /* normal stats should be invariant */ | 201 | /* normal stats should be invariant */ |
@@ -257,7 +230,7 @@ int test__hists_filter(void) | |||
257 | 230 | ||
258 | if (verbose > 2) { | 231 | if (verbose > 2) { |
259 | pr_info("Histogram for symbol filter\n"); | 232 | pr_info("Histogram for symbol filter\n"); |
260 | print_hists(hists); | 233 | print_hists_out(hists); |
261 | } | 234 | } |
262 | 235 | ||
263 | /* normal stats should be invariant */ | 236 | /* normal stats should be invariant */ |
@@ -284,7 +257,7 @@ int test__hists_filter(void) | |||
284 | 257 | ||
285 | if (verbose > 2) { | 258 | if (verbose > 2) { |
286 | pr_info("Histogram for all filters\n"); | 259 | pr_info("Histogram for all filters\n"); |
287 | print_hists(hists); | 260 | print_hists_out(hists); |
288 | } | 261 | } |
289 | 262 | ||
290 | /* normal stats should be invariant */ | 263 | /* normal stats should be invariant */ |
@@ -310,6 +283,7 @@ int test__hists_filter(void) | |||
310 | out: | 283 | out: |
311 | /* tear down everything */ | 284 | /* tear down everything */ |
312 | perf_evlist__delete(evlist); | 285 | perf_evlist__delete(evlist); |
286 | reset_output_field(); | ||
313 | machines__exit(&machines); | 287 | machines__exit(&machines); |
314 | 288 | ||
315 | return err; | 289 | return err; |
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index b009bbf440d9..5ffa2c3eb77d 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c | |||
@@ -268,33 +268,6 @@ static int validate_link(struct hists *leader, struct hists *other) | |||
268 | return __validate_link(leader, 0) || __validate_link(other, 1); | 268 | return __validate_link(leader, 0) || __validate_link(other, 1); |
269 | } | 269 | } |
270 | 270 | ||
271 | static void print_hists(struct hists *hists) | ||
272 | { | ||
273 | int i = 0; | ||
274 | struct rb_root *root; | ||
275 | struct rb_node *node; | ||
276 | |||
277 | if (sort__need_collapse) | ||
278 | root = &hists->entries_collapsed; | ||
279 | else | ||
280 | root = hists->entries_in; | ||
281 | |||
282 | pr_info("----- %s --------\n", __func__); | ||
283 | node = rb_first(root); | ||
284 | while (node) { | ||
285 | struct hist_entry *he; | ||
286 | |||
287 | he = rb_entry(node, struct hist_entry, rb_node_in); | ||
288 | |||
289 | pr_info("%2d: entry: %-8s [%-8s] %20s: period = %"PRIu64"\n", | ||
290 | i, thread__comm_str(he->thread), he->ms.map->dso->short_name, | ||
291 | he->ms.sym->name, he->stat.period); | ||
292 | |||
293 | i++; | ||
294 | node = rb_next(node); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | int test__hists_link(void) | 271 | int test__hists_link(void) |
299 | { | 272 | { |
300 | int err = -1; | 273 | int err = -1; |
@@ -336,7 +309,7 @@ int test__hists_link(void) | |||
336 | hists__collapse_resort(&evsel->hists, NULL); | 309 | hists__collapse_resort(&evsel->hists, NULL); |
337 | 310 | ||
338 | if (verbose > 2) | 311 | if (verbose > 2) |
339 | print_hists(&evsel->hists); | 312 | print_hists_in(&evsel->hists); |
340 | } | 313 | } |
341 | 314 | ||
342 | first = perf_evlist__first(evlist); | 315 | first = perf_evlist__first(evlist); |
@@ -359,6 +332,7 @@ int test__hists_link(void) | |||
359 | out: | 332 | out: |
360 | /* tear down everything */ | 333 | /* tear down everything */ |
361 | perf_evlist__delete(evlist); | 334 | perf_evlist__delete(evlist); |
335 | reset_output_field(); | ||
362 | machines__exit(&machines); | 336 | machines__exit(&machines); |
363 | 337 | ||
364 | return err; | 338 | return err; |
diff --git a/tools/perf/tests/hists_output.c b/tools/perf/tests/hists_output.c new file mode 100644 index 000000000000..a16850551797 --- /dev/null +++ b/tools/perf/tests/hists_output.c | |||
@@ -0,0 +1,618 @@ | |||
1 | #include "perf.h" | ||
2 | #include "util/debug.h" | ||
3 | #include "util/symbol.h" | ||
4 | #include "util/sort.h" | ||
5 | #include "util/evsel.h" | ||
6 | #include "util/evlist.h" | ||
7 | #include "util/machine.h" | ||
8 | #include "util/thread.h" | ||
9 | #include "util/parse-events.h" | ||
10 | #include "tests/tests.h" | ||
11 | #include "tests/hists_common.h" | ||
12 | |||
13 | struct sample { | ||
14 | u32 cpu; | ||
15 | u32 pid; | ||
16 | u64 ip; | ||
17 | struct thread *thread; | ||
18 | struct map *map; | ||
19 | struct symbol *sym; | ||
20 | }; | ||
21 | |||
22 | /* For the numbers, see hists_common.c */ | ||
23 | static struct sample fake_samples[] = { | ||
24 | /* perf [kernel] schedule() */ | ||
25 | { .cpu = 0, .pid = 100, .ip = 0xf0000 + 700, }, | ||
26 | /* perf [perf] main() */ | ||
27 | { .cpu = 1, .pid = 100, .ip = 0x40000 + 700, }, | ||
28 | /* perf [perf] cmd_record() */ | ||
29 | { .cpu = 1, .pid = 100, .ip = 0x40000 + 900, }, | ||
30 | /* perf [libc] malloc() */ | ||
31 | { .cpu = 1, .pid = 100, .ip = 0x50000 + 700, }, | ||
32 | /* perf [libc] free() */ | ||
33 | { .cpu = 2, .pid = 100, .ip = 0x50000 + 800, }, | ||
34 | /* perf [perf] main() */ | ||
35 | { .cpu = 2, .pid = 200, .ip = 0x40000 + 700, }, | ||
36 | /* perf [kernel] page_fault() */ | ||
37 | { .cpu = 2, .pid = 200, .ip = 0xf0000 + 800, }, | ||
38 | /* bash [bash] main() */ | ||
39 | { .cpu = 3, .pid = 300, .ip = 0x40000 + 700, }, | ||
40 | /* bash [bash] xmalloc() */ | ||
41 | { .cpu = 0, .pid = 300, .ip = 0x40000 + 800, }, | ||
42 | /* bash [kernel] page_fault() */ | ||
43 | { .cpu = 1, .pid = 300, .ip = 0xf0000 + 800, }, | ||
44 | }; | ||
45 | |||
46 | static int add_hist_entries(struct hists *hists, struct machine *machine) | ||
47 | { | ||
48 | struct addr_location al; | ||
49 | struct hist_entry *he; | ||
50 | struct perf_sample sample = { .period = 100, }; | ||
51 | size_t i; | ||
52 | |||
53 | for (i = 0; i < ARRAY_SIZE(fake_samples); i++) { | ||
54 | const union perf_event event = { | ||
55 | .header = { | ||
56 | .misc = PERF_RECORD_MISC_USER, | ||
57 | }, | ||
58 | }; | ||
59 | |||
60 | sample.cpu = fake_samples[i].cpu; | ||
61 | sample.pid = fake_samples[i].pid; | ||
62 | sample.tid = fake_samples[i].pid; | ||
63 | sample.ip = fake_samples[i].ip; | ||
64 | |||
65 | if (perf_event__preprocess_sample(&event, machine, &al, | ||
66 | &sample) < 0) | ||
67 | goto out; | ||
68 | |||
69 | he = __hists__add_entry(hists, &al, NULL, NULL, NULL, | ||
70 | sample.period, 1, 0); | ||
71 | if (he == NULL) | ||
72 | goto out; | ||
73 | |||
74 | fake_samples[i].thread = al.thread; | ||
75 | fake_samples[i].map = al.map; | ||
76 | fake_samples[i].sym = al.sym; | ||
77 | } | ||
78 | |||
79 | return TEST_OK; | ||
80 | |||
81 | out: | ||
82 | pr_debug("Not enough memory for adding a hist entry\n"); | ||
83 | return TEST_FAIL; | ||
84 | } | ||
85 | |||
86 | static void del_hist_entries(struct hists *hists) | ||
87 | { | ||
88 | struct hist_entry *he; | ||
89 | struct rb_root *root_in; | ||
90 | struct rb_root *root_out; | ||
91 | struct rb_node *node; | ||
92 | |||
93 | if (sort__need_collapse) | ||
94 | root_in = &hists->entries_collapsed; | ||
95 | else | ||
96 | root_in = hists->entries_in; | ||
97 | |||
98 | root_out = &hists->entries; | ||
99 | |||
100 | while (!RB_EMPTY_ROOT(root_out)) { | ||
101 | node = rb_first(root_out); | ||
102 | |||
103 | he = rb_entry(node, struct hist_entry, rb_node); | ||
104 | rb_erase(node, root_out); | ||
105 | rb_erase(&he->rb_node_in, root_in); | ||
106 | hist_entry__free(he); | ||
107 | } | ||
108 | } | ||
109 | |||
110 | typedef int (*test_fn_t)(struct perf_evsel *, struct machine *); | ||
111 | |||
112 | #define COMM(he) (thread__comm_str(he->thread)) | ||
113 | #define DSO(he) (he->ms.map->dso->short_name) | ||
114 | #define SYM(he) (he->ms.sym->name) | ||
115 | #define CPU(he) (he->cpu) | ||
116 | #define PID(he) (he->thread->tid) | ||
117 | |||
118 | /* default sort keys (no field) */ | ||
119 | static int test1(struct perf_evsel *evsel, struct machine *machine) | ||
120 | { | ||
121 | int err; | ||
122 | struct hists *hists = &evsel->hists; | ||
123 | struct hist_entry *he; | ||
124 | struct rb_root *root; | ||
125 | struct rb_node *node; | ||
126 | |||
127 | field_order = NULL; | ||
128 | sort_order = NULL; /* equivalent to sort_order = "comm,dso,sym" */ | ||
129 | |||
130 | setup_sorting(); | ||
131 | |||
132 | /* | ||
133 | * expected output: | ||
134 | * | ||
135 | * Overhead Command Shared Object Symbol | ||
136 | * ======== ======= ============= ============== | ||
137 | * 20.00% perf perf [.] main | ||
138 | * 10.00% bash [kernel] [k] page_fault | ||
139 | * 10.00% bash bash [.] main | ||
140 | * 10.00% bash bash [.] xmalloc | ||
141 | * 10.00% perf [kernel] [k] page_fault | ||
142 | * 10.00% perf [kernel] [k] schedule | ||
143 | * 10.00% perf libc [.] free | ||
144 | * 10.00% perf libc [.] malloc | ||
145 | * 10.00% perf perf [.] cmd_record | ||
146 | */ | ||
147 | err = add_hist_entries(hists, machine); | ||
148 | if (err < 0) | ||
149 | goto out; | ||
150 | |||
151 | hists__collapse_resort(hists, NULL); | ||
152 | hists__output_resort(hists); | ||
153 | |||
154 | if (verbose > 2) { | ||
155 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | ||
156 | print_hists_out(hists); | ||
157 | } | ||
158 | |||
159 | root = &evsel->hists.entries; | ||
160 | node = rb_first(root); | ||
161 | he = rb_entry(node, struct hist_entry, rb_node); | ||
162 | TEST_ASSERT_VAL("Invalid hist entry", | ||
163 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | ||
164 | !strcmp(SYM(he), "main") && he->stat.period == 200); | ||
165 | |||
166 | node = rb_next(node); | ||
167 | he = rb_entry(node, struct hist_entry, rb_node); | ||
168 | TEST_ASSERT_VAL("Invalid hist entry", | ||
169 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && | ||
170 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | ||
171 | |||
172 | node = rb_next(node); | ||
173 | he = rb_entry(node, struct hist_entry, rb_node); | ||
174 | TEST_ASSERT_VAL("Invalid hist entry", | ||
175 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | ||
176 | !strcmp(SYM(he), "main") && he->stat.period == 100); | ||
177 | |||
178 | node = rb_next(node); | ||
179 | he = rb_entry(node, struct hist_entry, rb_node); | ||
180 | TEST_ASSERT_VAL("Invalid hist entry", | ||
181 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | ||
182 | !strcmp(SYM(he), "xmalloc") && he->stat.period == 100); | ||
183 | |||
184 | node = rb_next(node); | ||
185 | he = rb_entry(node, struct hist_entry, rb_node); | ||
186 | TEST_ASSERT_VAL("Invalid hist entry", | ||
187 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | ||
188 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | ||
189 | |||
190 | node = rb_next(node); | ||
191 | he = rb_entry(node, struct hist_entry, rb_node); | ||
192 | TEST_ASSERT_VAL("Invalid hist entry", | ||
193 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | ||
194 | !strcmp(SYM(he), "schedule") && he->stat.period == 100); | ||
195 | |||
196 | node = rb_next(node); | ||
197 | he = rb_entry(node, struct hist_entry, rb_node); | ||
198 | TEST_ASSERT_VAL("Invalid hist entry", | ||
199 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | ||
200 | !strcmp(SYM(he), "free") && he->stat.period == 100); | ||
201 | |||
202 | node = rb_next(node); | ||
203 | he = rb_entry(node, struct hist_entry, rb_node); | ||
204 | TEST_ASSERT_VAL("Invalid hist entry", | ||
205 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | ||
206 | !strcmp(SYM(he), "malloc") && he->stat.period == 100); | ||
207 | |||
208 | node = rb_next(node); | ||
209 | he = rb_entry(node, struct hist_entry, rb_node); | ||
210 | TEST_ASSERT_VAL("Invalid hist entry", | ||
211 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | ||
212 | !strcmp(SYM(he), "cmd_record") && he->stat.period == 100); | ||
213 | |||
214 | out: | ||
215 | del_hist_entries(hists); | ||
216 | reset_output_field(); | ||
217 | return err; | ||
218 | } | ||
219 | |||
220 | /* mixed fields and sort keys */ | ||
221 | static int test2(struct perf_evsel *evsel, struct machine *machine) | ||
222 | { | ||
223 | int err; | ||
224 | struct hists *hists = &evsel->hists; | ||
225 | struct hist_entry *he; | ||
226 | struct rb_root *root; | ||
227 | struct rb_node *node; | ||
228 | |||
229 | field_order = "overhead,cpu"; | ||
230 | sort_order = "pid"; | ||
231 | |||
232 | setup_sorting(); | ||
233 | |||
234 | /* | ||
235 | * expected output: | ||
236 | * | ||
237 | * Overhead CPU Command: Pid | ||
238 | * ======== === ============= | ||
239 | * 30.00% 1 perf : 100 | ||
240 | * 10.00% 0 perf : 100 | ||
241 | * 10.00% 2 perf : 100 | ||
242 | * 20.00% 2 perf : 200 | ||
243 | * 10.00% 0 bash : 300 | ||
244 | * 10.00% 1 bash : 300 | ||
245 | * 10.00% 3 bash : 300 | ||
246 | */ | ||
247 | err = add_hist_entries(hists, machine); | ||
248 | if (err < 0) | ||
249 | goto out; | ||
250 | |||
251 | hists__collapse_resort(hists, NULL); | ||
252 | hists__output_resort(hists); | ||
253 | |||
254 | if (verbose > 2) { | ||
255 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | ||
256 | print_hists_out(hists); | ||
257 | } | ||
258 | |||
259 | root = &evsel->hists.entries; | ||
260 | node = rb_first(root); | ||
261 | he = rb_entry(node, struct hist_entry, rb_node); | ||
262 | TEST_ASSERT_VAL("Invalid hist entry", | ||
263 | CPU(he) == 1 && PID(he) == 100 && he->stat.period == 300); | ||
264 | |||
265 | node = rb_next(node); | ||
266 | he = rb_entry(node, struct hist_entry, rb_node); | ||
267 | TEST_ASSERT_VAL("Invalid hist entry", | ||
268 | CPU(he) == 0 && PID(he) == 100 && he->stat.period == 100); | ||
269 | |||
270 | out: | ||
271 | del_hist_entries(hists); | ||
272 | reset_output_field(); | ||
273 | return err; | ||
274 | } | ||
275 | |||
276 | /* fields only (no sort key) */ | ||
277 | static int test3(struct perf_evsel *evsel, struct machine *machine) | ||
278 | { | ||
279 | int err; | ||
280 | struct hists *hists = &evsel->hists; | ||
281 | struct hist_entry *he; | ||
282 | struct rb_root *root; | ||
283 | struct rb_node *node; | ||
284 | |||
285 | field_order = "comm,overhead,dso"; | ||
286 | sort_order = NULL; | ||
287 | |||
288 | setup_sorting(); | ||
289 | |||
290 | /* | ||
291 | * expected output: | ||
292 | * | ||
293 | * Command Overhead Shared Object | ||
294 | * ======= ======== ============= | ||
295 | * bash 20.00% bash | ||
296 | * bash 10.00% [kernel] | ||
297 | * perf 30.00% perf | ||
298 | * perf 20.00% [kernel] | ||
299 | * perf 20.00% libc | ||
300 | */ | ||
301 | err = add_hist_entries(hists, machine); | ||
302 | if (err < 0) | ||
303 | goto out; | ||
304 | |||
305 | hists__collapse_resort(hists, NULL); | ||
306 | hists__output_resort(hists); | ||
307 | |||
308 | if (verbose > 2) { | ||
309 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | ||
310 | print_hists_out(hists); | ||
311 | } | ||
312 | |||
313 | root = &evsel->hists.entries; | ||
314 | node = rb_first(root); | ||
315 | he = rb_entry(node, struct hist_entry, rb_node); | ||
316 | TEST_ASSERT_VAL("Invalid hist entry", | ||
317 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | ||
318 | he->stat.period == 200); | ||
319 | |||
320 | node = rb_next(node); | ||
321 | he = rb_entry(node, struct hist_entry, rb_node); | ||
322 | TEST_ASSERT_VAL("Invalid hist entry", | ||
323 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && | ||
324 | he->stat.period == 100); | ||
325 | |||
326 | node = rb_next(node); | ||
327 | he = rb_entry(node, struct hist_entry, rb_node); | ||
328 | TEST_ASSERT_VAL("Invalid hist entry", | ||
329 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | ||
330 | he->stat.period == 300); | ||
331 | |||
332 | node = rb_next(node); | ||
333 | he = rb_entry(node, struct hist_entry, rb_node); | ||
334 | TEST_ASSERT_VAL("Invalid hist entry", | ||
335 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | ||
336 | he->stat.period == 200); | ||
337 | |||
338 | node = rb_next(node); | ||
339 | he = rb_entry(node, struct hist_entry, rb_node); | ||
340 | TEST_ASSERT_VAL("Invalid hist entry", | ||
341 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | ||
342 | he->stat.period == 200); | ||
343 | |||
344 | out: | ||
345 | del_hist_entries(hists); | ||
346 | reset_output_field(); | ||
347 | return err; | ||
348 | } | ||
349 | |||
350 | /* handle duplicate 'dso' field */ | ||
351 | static int test4(struct perf_evsel *evsel, struct machine *machine) | ||
352 | { | ||
353 | int err; | ||
354 | struct hists *hists = &evsel->hists; | ||
355 | struct hist_entry *he; | ||
356 | struct rb_root *root; | ||
357 | struct rb_node *node; | ||
358 | |||
359 | field_order = "dso,sym,comm,overhead,dso"; | ||
360 | sort_order = "sym"; | ||
361 | |||
362 | setup_sorting(); | ||
363 | |||
364 | /* | ||
365 | * expected output: | ||
366 | * | ||
367 | * Shared Object Symbol Command Overhead | ||
368 | * ============= ============== ======= ======== | ||
369 | * perf [.] cmd_record perf 10.00% | ||
370 | * libc [.] free perf 10.00% | ||
371 | * bash [.] main bash 10.00% | ||
372 | * perf [.] main perf 20.00% | ||
373 | * libc [.] malloc perf 10.00% | ||
374 | * [kernel] [k] page_fault bash 10.00% | ||
375 | * [kernel] [k] page_fault perf 10.00% | ||
376 | * [kernel] [k] schedule perf 10.00% | ||
377 | * bash [.] xmalloc bash 10.00% | ||
378 | */ | ||
379 | err = add_hist_entries(hists, machine); | ||
380 | if (err < 0) | ||
381 | goto out; | ||
382 | |||
383 | hists__collapse_resort(hists, NULL); | ||
384 | hists__output_resort(hists); | ||
385 | |||
386 | if (verbose > 2) { | ||
387 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | ||
388 | print_hists_out(hists); | ||
389 | } | ||
390 | |||
391 | root = &evsel->hists.entries; | ||
392 | node = rb_first(root); | ||
393 | he = rb_entry(node, struct hist_entry, rb_node); | ||
394 | TEST_ASSERT_VAL("Invalid hist entry", | ||
395 | !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "cmd_record") && | ||
396 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | ||
397 | |||
398 | node = rb_next(node); | ||
399 | he = rb_entry(node, struct hist_entry, rb_node); | ||
400 | TEST_ASSERT_VAL("Invalid hist entry", | ||
401 | !strcmp(DSO(he), "libc") && !strcmp(SYM(he), "free") && | ||
402 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | ||
403 | |||
404 | node = rb_next(node); | ||
405 | he = rb_entry(node, struct hist_entry, rb_node); | ||
406 | TEST_ASSERT_VAL("Invalid hist entry", | ||
407 | !strcmp(DSO(he), "bash") && !strcmp(SYM(he), "main") && | ||
408 | !strcmp(COMM(he), "bash") && he->stat.period == 100); | ||
409 | |||
410 | node = rb_next(node); | ||
411 | he = rb_entry(node, struct hist_entry, rb_node); | ||
412 | TEST_ASSERT_VAL("Invalid hist entry", | ||
413 | !strcmp(DSO(he), "perf") && !strcmp(SYM(he), "main") && | ||
414 | !strcmp(COMM(he), "perf") && he->stat.period == 200); | ||
415 | |||
416 | node = rb_next(node); | ||
417 | he = rb_entry(node, struct hist_entry, rb_node); | ||
418 | TEST_ASSERT_VAL("Invalid hist entry", | ||
419 | !strcmp(DSO(he), "libc") && !strcmp(SYM(he), "malloc") && | ||
420 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | ||
421 | |||
422 | node = rb_next(node); | ||
423 | he = rb_entry(node, struct hist_entry, rb_node); | ||
424 | TEST_ASSERT_VAL("Invalid hist entry", | ||
425 | !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") && | ||
426 | !strcmp(COMM(he), "bash") && he->stat.period == 100); | ||
427 | |||
428 | node = rb_next(node); | ||
429 | he = rb_entry(node, struct hist_entry, rb_node); | ||
430 | TEST_ASSERT_VAL("Invalid hist entry", | ||
431 | !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "page_fault") && | ||
432 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | ||
433 | |||
434 | node = rb_next(node); | ||
435 | he = rb_entry(node, struct hist_entry, rb_node); | ||
436 | TEST_ASSERT_VAL("Invalid hist entry", | ||
437 | !strcmp(DSO(he), "[kernel]") && !strcmp(SYM(he), "schedule") && | ||
438 | !strcmp(COMM(he), "perf") && he->stat.period == 100); | ||
439 | |||
440 | node = rb_next(node); | ||
441 | he = rb_entry(node, struct hist_entry, rb_node); | ||
442 | TEST_ASSERT_VAL("Invalid hist entry", | ||
443 | !strcmp(DSO(he), "bash") && !strcmp(SYM(he), "xmalloc") && | ||
444 | !strcmp(COMM(he), "bash") && he->stat.period == 100); | ||
445 | |||
446 | out: | ||
447 | del_hist_entries(hists); | ||
448 | reset_output_field(); | ||
449 | return err; | ||
450 | } | ||
451 | |||
452 | /* full sort keys w/o overhead field */ | ||
453 | static int test5(struct perf_evsel *evsel, struct machine *machine) | ||
454 | { | ||
455 | int err; | ||
456 | struct hists *hists = &evsel->hists; | ||
457 | struct hist_entry *he; | ||
458 | struct rb_root *root; | ||
459 | struct rb_node *node; | ||
460 | |||
461 | field_order = "cpu,pid,comm,dso,sym"; | ||
462 | sort_order = "dso,pid"; | ||
463 | |||
464 | setup_sorting(); | ||
465 | |||
466 | /* | ||
467 | * expected output: | ||
468 | * | ||
469 | * CPU Command: Pid Command Shared Object Symbol | ||
470 | * === ============= ======= ============= ============== | ||
471 | * 0 perf: 100 perf [kernel] [k] schedule | ||
472 | * 2 perf: 200 perf [kernel] [k] page_fault | ||
473 | * 1 bash: 300 bash [kernel] [k] page_fault | ||
474 | * 0 bash: 300 bash bash [.] xmalloc | ||
475 | * 3 bash: 300 bash bash [.] main | ||
476 | * 1 perf: 100 perf libc [.] malloc | ||
477 | * 2 perf: 100 perf libc [.] free | ||
478 | * 1 perf: 100 perf perf [.] cmd_record | ||
479 | * 1 perf: 100 perf perf [.] main | ||
480 | * 2 perf: 200 perf perf [.] main | ||
481 | */ | ||
482 | err = add_hist_entries(hists, machine); | ||
483 | if (err < 0) | ||
484 | goto out; | ||
485 | |||
486 | hists__collapse_resort(hists, NULL); | ||
487 | hists__output_resort(hists); | ||
488 | |||
489 | if (verbose > 2) { | ||
490 | pr_info("[fields = %s, sort = %s]\n", field_order, sort_order); | ||
491 | print_hists_out(hists); | ||
492 | } | ||
493 | |||
494 | root = &evsel->hists.entries; | ||
495 | node = rb_first(root); | ||
496 | he = rb_entry(node, struct hist_entry, rb_node); | ||
497 | |||
498 | TEST_ASSERT_VAL("Invalid hist entry", | ||
499 | CPU(he) == 0 && PID(he) == 100 && | ||
500 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | ||
501 | !strcmp(SYM(he), "schedule") && he->stat.period == 100); | ||
502 | |||
503 | node = rb_next(node); | ||
504 | he = rb_entry(node, struct hist_entry, rb_node); | ||
505 | TEST_ASSERT_VAL("Invalid hist entry", | ||
506 | CPU(he) == 2 && PID(he) == 200 && | ||
507 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "[kernel]") && | ||
508 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | ||
509 | |||
510 | node = rb_next(node); | ||
511 | he = rb_entry(node, struct hist_entry, rb_node); | ||
512 | TEST_ASSERT_VAL("Invalid hist entry", | ||
513 | CPU(he) == 1 && PID(he) == 300 && | ||
514 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "[kernel]") && | ||
515 | !strcmp(SYM(he), "page_fault") && he->stat.period == 100); | ||
516 | |||
517 | node = rb_next(node); | ||
518 | he = rb_entry(node, struct hist_entry, rb_node); | ||
519 | TEST_ASSERT_VAL("Invalid hist entry", | ||
520 | CPU(he) == 0 && PID(he) == 300 && | ||
521 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | ||
522 | !strcmp(SYM(he), "xmalloc") && he->stat.period == 100); | ||
523 | |||
524 | node = rb_next(node); | ||
525 | he = rb_entry(node, struct hist_entry, rb_node); | ||
526 | TEST_ASSERT_VAL("Invalid hist entry", | ||
527 | CPU(he) == 3 && PID(he) == 300 && | ||
528 | !strcmp(COMM(he), "bash") && !strcmp(DSO(he), "bash") && | ||
529 | !strcmp(SYM(he), "main") && he->stat.period == 100); | ||
530 | |||
531 | node = rb_next(node); | ||
532 | he = rb_entry(node, struct hist_entry, rb_node); | ||
533 | TEST_ASSERT_VAL("Invalid hist entry", | ||
534 | CPU(he) == 1 && PID(he) == 100 && | ||
535 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | ||
536 | !strcmp(SYM(he), "malloc") && he->stat.period == 100); | ||
537 | |||
538 | node = rb_next(node); | ||
539 | he = rb_entry(node, struct hist_entry, rb_node); | ||
540 | TEST_ASSERT_VAL("Invalid hist entry", | ||
541 | CPU(he) == 2 && PID(he) == 100 && | ||
542 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "libc") && | ||
543 | !strcmp(SYM(he), "free") && he->stat.period == 100); | ||
544 | |||
545 | node = rb_next(node); | ||
546 | he = rb_entry(node, struct hist_entry, rb_node); | ||
547 | TEST_ASSERT_VAL("Invalid hist entry", | ||
548 | CPU(he) == 1 && PID(he) == 100 && | ||
549 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | ||
550 | !strcmp(SYM(he), "cmd_record") && he->stat.period == 100); | ||
551 | |||
552 | node = rb_next(node); | ||
553 | he = rb_entry(node, struct hist_entry, rb_node); | ||
554 | TEST_ASSERT_VAL("Invalid hist entry", | ||
555 | CPU(he) == 1 && PID(he) == 100 && | ||
556 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | ||
557 | !strcmp(SYM(he), "main") && he->stat.period == 100); | ||
558 | |||
559 | node = rb_next(node); | ||
560 | he = rb_entry(node, struct hist_entry, rb_node); | ||
561 | TEST_ASSERT_VAL("Invalid hist entry", | ||
562 | CPU(he) == 2 && PID(he) == 200 && | ||
563 | !strcmp(COMM(he), "perf") && !strcmp(DSO(he), "perf") && | ||
564 | !strcmp(SYM(he), "main") && he->stat.period == 100); | ||
565 | |||
566 | out: | ||
567 | del_hist_entries(hists); | ||
568 | reset_output_field(); | ||
569 | return err; | ||
570 | } | ||
571 | |||
572 | int test__hists_output(void) | ||
573 | { | ||
574 | int err = TEST_FAIL; | ||
575 | struct machines machines; | ||
576 | struct machine *machine; | ||
577 | struct perf_evsel *evsel; | ||
578 | struct perf_evlist *evlist = perf_evlist__new(); | ||
579 | size_t i; | ||
580 | test_fn_t testcases[] = { | ||
581 | test1, | ||
582 | test2, | ||
583 | test3, | ||
584 | test4, | ||
585 | test5, | ||
586 | }; | ||
587 | |||
588 | TEST_ASSERT_VAL("No memory", evlist); | ||
589 | |||
590 | err = parse_events(evlist, "cpu-clock"); | ||
591 | if (err) | ||
592 | goto out; | ||
593 | |||
594 | machines__init(&machines); | ||
595 | |||
596 | /* setup threads/dso/map/symbols also */ | ||
597 | machine = setup_fake_machine(&machines); | ||
598 | if (!machine) | ||
599 | goto out; | ||
600 | |||
601 | if (verbose > 1) | ||
602 | machine__fprintf(machine, stderr); | ||
603 | |||
604 | evsel = perf_evlist__first(evlist); | ||
605 | |||
606 | for (i = 0; i < ARRAY_SIZE(testcases); i++) { | ||
607 | err = testcases[i](evsel, machine); | ||
608 | if (err < 0) | ||
609 | break; | ||
610 | } | ||
611 | |||
612 | out: | ||
613 | /* tear down everything */ | ||
614 | perf_evlist__delete(evlist); | ||
615 | machines__exit(&machines); | ||
616 | |||
617 | return err; | ||
618 | } | ||
diff --git a/tools/perf/tests/tests.h b/tools/perf/tests/tests.h index 8f91fb051ef1..d76c0e2e6635 100644 --- a/tools/perf/tests/tests.h +++ b/tools/perf/tests/tests.h | |||
@@ -44,6 +44,7 @@ int test__dwarf_unwind(void); | |||
44 | int test__hists_filter(void); | 44 | int test__hists_filter(void); |
45 | int test__mmap_thread_lookup(void); | 45 | int test__mmap_thread_lookup(void); |
46 | int test__thread_mg_share(void); | 46 | int test__thread_mg_share(void); |
47 | int test__hists_output(void); | ||
47 | 48 | ||
48 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) | 49 | #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) |
49 | #ifdef HAVE_DWARF_UNWIND_SUPPORT | 50 | #ifdef HAVE_DWARF_UNWIND_SUPPORT |