]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - tools/perf/tests/hists_filter.c
Merge branch 'drm-next-4.12' of git://people.freedesktop.org/~agd5f/linux into drm...
[mirror_ubuntu-artful-kernel.git] / tools / perf / tests / hists_filter.c
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 #include <linux/kernel.h>
13
14 struct sample {
15 u32 pid;
16 u64 ip;
17 struct thread *thread;
18 struct map *map;
19 struct symbol *sym;
20 int socket;
21 };
22
23 /* For the numbers, see hists_common.c */
24 static struct sample fake_samples[] = {
25 /* perf [kernel] schedule() */
26 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 },
27 /* perf [perf] main() */
28 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 },
29 /* perf [libc] malloc() */
30 { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 },
31 /* perf [perf] main() */
32 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */
33 /* perf [perf] cmd_record() */
34 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 },
35 /* perf [kernel] page_fault() */
36 { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 },
37 /* bash [bash] main() */
38 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, .socket = 2 },
39 /* bash [bash] xmalloc() */
40 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 },
41 /* bash [libc] malloc() */
42 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 },
43 /* bash [kernel] page_fault() */
44 { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
45 };
46
47 static int add_hist_entries(struct perf_evlist *evlist,
48 struct machine *machine)
49 {
50 struct perf_evsel *evsel;
51 struct addr_location al;
52 struct perf_sample sample = { .period = 100, };
53 size_t i;
54
55 /*
56 * each evsel will have 10 samples but the 4th sample
57 * (perf [perf] main) will be collapsed to an existing entry
58 * so total 9 entries will be in the tree.
59 */
60 evlist__for_each_entry(evlist, evsel) {
61 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
62 struct hist_entry_iter iter = {
63 .evsel = evsel,
64 .sample = &sample,
65 .ops = &hist_iter_normal,
66 .hide_unresolved = false,
67 };
68 struct hists *hists = evsel__hists(evsel);
69
70 /* make sure it has no filter at first */
71 hists->thread_filter = NULL;
72 hists->dso_filter = NULL;
73 hists->symbol_filter_str = NULL;
74
75 sample.cpumode = PERF_RECORD_MISC_USER;
76 sample.pid = fake_samples[i].pid;
77 sample.tid = fake_samples[i].pid;
78 sample.ip = fake_samples[i].ip;
79
80 if (machine__resolve(machine, &al, &sample) < 0)
81 goto out;
82
83 al.socket = fake_samples[i].socket;
84 if (hist_entry_iter__add(&iter, &al,
85 sysctl_perf_event_max_stack, NULL) < 0) {
86 addr_location__put(&al);
87 goto out;
88 }
89
90 fake_samples[i].thread = al.thread;
91 fake_samples[i].map = al.map;
92 fake_samples[i].sym = al.sym;
93 }
94 }
95
96 return 0;
97
98 out:
99 pr_debug("Not enough memory for adding a hist entry\n");
100 return TEST_FAIL;
101 }
102
103 int test__hists_filter(int subtest __maybe_unused)
104 {
105 int err = TEST_FAIL;
106 struct machines machines;
107 struct machine *machine;
108 struct perf_evsel *evsel;
109 struct perf_evlist *evlist = perf_evlist__new();
110
111 TEST_ASSERT_VAL("No memory", evlist);
112
113 err = parse_events(evlist, "cpu-clock", NULL);
114 if (err)
115 goto out;
116 err = parse_events(evlist, "task-clock", NULL);
117 if (err)
118 goto out;
119 err = TEST_FAIL;
120
121 /* default sort order (comm,dso,sym) will be used */
122 if (setup_sorting(NULL) < 0)
123 goto out;
124
125 machines__init(&machines);
126
127 /* setup threads/dso/map/symbols also */
128 machine = setup_fake_machine(&machines);
129 if (!machine)
130 goto out;
131
132 if (verbose > 1)
133 machine__fprintf(machine, stderr);
134
135 /* process sample events */
136 err = add_hist_entries(evlist, machine);
137 if (err < 0)
138 goto out;
139
140 evlist__for_each_entry(evlist, evsel) {
141 struct hists *hists = evsel__hists(evsel);
142
143 hists__collapse_resort(hists, NULL);
144 perf_evsel__output_resort(evsel, NULL);
145
146 if (verbose > 2) {
147 pr_info("Normal histogram\n");
148 print_hists_out(hists);
149 }
150
151 TEST_ASSERT_VAL("Invalid nr samples",
152 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
153 TEST_ASSERT_VAL("Invalid nr hist entries",
154 hists->nr_entries == 9);
155 TEST_ASSERT_VAL("Invalid total period",
156 hists->stats.total_period == 1000);
157 TEST_ASSERT_VAL("Unmatched nr samples",
158 hists->stats.nr_events[PERF_RECORD_SAMPLE] ==
159 hists->stats.nr_non_filtered_samples);
160 TEST_ASSERT_VAL("Unmatched nr hist entries",
161 hists->nr_entries == hists->nr_non_filtered_entries);
162 TEST_ASSERT_VAL("Unmatched total period",
163 hists->stats.total_period ==
164 hists->stats.total_non_filtered_period);
165
166 /* now applying thread filter for 'bash' */
167 hists->thread_filter = fake_samples[9].thread;
168 hists__filter_by_thread(hists);
169
170 if (verbose > 2) {
171 pr_info("Histogram for thread filter\n");
172 print_hists_out(hists);
173 }
174
175 /* normal stats should be invariant */
176 TEST_ASSERT_VAL("Invalid nr samples",
177 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
178 TEST_ASSERT_VAL("Invalid nr hist entries",
179 hists->nr_entries == 9);
180 TEST_ASSERT_VAL("Invalid total period",
181 hists->stats.total_period == 1000);
182
183 /* but filter stats are changed */
184 TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
185 hists->stats.nr_non_filtered_samples == 4);
186 TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
187 hists->nr_non_filtered_entries == 4);
188 TEST_ASSERT_VAL("Unmatched total period for thread filter",
189 hists->stats.total_non_filtered_period == 400);
190
191 /* remove thread filter first */
192 hists->thread_filter = NULL;
193 hists__filter_by_thread(hists);
194
195 /* now applying dso filter for 'kernel' */
196 hists->dso_filter = fake_samples[0].map->dso;
197 hists__filter_by_dso(hists);
198
199 if (verbose > 2) {
200 pr_info("Histogram for dso filter\n");
201 print_hists_out(hists);
202 }
203
204 /* normal stats should be invariant */
205 TEST_ASSERT_VAL("Invalid nr samples",
206 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
207 TEST_ASSERT_VAL("Invalid nr hist entries",
208 hists->nr_entries == 9);
209 TEST_ASSERT_VAL("Invalid total period",
210 hists->stats.total_period == 1000);
211
212 /* but filter stats are changed */
213 TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
214 hists->stats.nr_non_filtered_samples == 3);
215 TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
216 hists->nr_non_filtered_entries == 3);
217 TEST_ASSERT_VAL("Unmatched total period for dso filter",
218 hists->stats.total_non_filtered_period == 300);
219
220 /* remove dso filter first */
221 hists->dso_filter = NULL;
222 hists__filter_by_dso(hists);
223
224 /*
225 * now applying symbol filter for 'main'. Also note that
226 * there's 3 samples that have 'main' symbol but the 4th
227 * entry of fake_samples was collapsed already so it won't
228 * be counted as a separate entry but the sample count and
229 * total period will be remained.
230 */
231 hists->symbol_filter_str = "main";
232 hists__filter_by_symbol(hists);
233
234 if (verbose > 2) {
235 pr_info("Histogram for symbol filter\n");
236 print_hists_out(hists);
237 }
238
239 /* normal stats should be invariant */
240 TEST_ASSERT_VAL("Invalid nr samples",
241 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
242 TEST_ASSERT_VAL("Invalid nr hist entries",
243 hists->nr_entries == 9);
244 TEST_ASSERT_VAL("Invalid total period",
245 hists->stats.total_period == 1000);
246
247 /* but filter stats are changed */
248 TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
249 hists->stats.nr_non_filtered_samples == 3);
250 TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
251 hists->nr_non_filtered_entries == 2);
252 TEST_ASSERT_VAL("Unmatched total period for symbol filter",
253 hists->stats.total_non_filtered_period == 300);
254
255 /* remove symbol filter first */
256 hists->symbol_filter_str = NULL;
257 hists__filter_by_symbol(hists);
258
259 /* now applying socket filters */
260 hists->socket_filter = 2;
261 hists__filter_by_socket(hists);
262
263 if (verbose > 2) {
264 pr_info("Histogram for socket filters\n");
265 print_hists_out(hists);
266 }
267
268 /* normal stats should be invariant */
269 TEST_ASSERT_VAL("Invalid nr samples",
270 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
271 TEST_ASSERT_VAL("Invalid nr hist entries",
272 hists->nr_entries == 9);
273 TEST_ASSERT_VAL("Invalid total period",
274 hists->stats.total_period == 1000);
275
276 /* but filter stats are changed */
277 TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
278 hists->stats.nr_non_filtered_samples == 2);
279 TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
280 hists->nr_non_filtered_entries == 2);
281 TEST_ASSERT_VAL("Unmatched total period for socket filter",
282 hists->stats.total_non_filtered_period == 200);
283
284 /* remove socket filter first */
285 hists->socket_filter = -1;
286 hists__filter_by_socket(hists);
287
288 /* now applying all filters at once. */
289 hists->thread_filter = fake_samples[1].thread;
290 hists->dso_filter = fake_samples[1].map->dso;
291 hists__filter_by_thread(hists);
292 hists__filter_by_dso(hists);
293
294 if (verbose > 2) {
295 pr_info("Histogram for all filters\n");
296 print_hists_out(hists);
297 }
298
299 /* normal stats should be invariant */
300 TEST_ASSERT_VAL("Invalid nr samples",
301 hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
302 TEST_ASSERT_VAL("Invalid nr hist entries",
303 hists->nr_entries == 9);
304 TEST_ASSERT_VAL("Invalid total period",
305 hists->stats.total_period == 1000);
306
307 /* but filter stats are changed */
308 TEST_ASSERT_VAL("Unmatched nr samples for all filter",
309 hists->stats.nr_non_filtered_samples == 2);
310 TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
311 hists->nr_non_filtered_entries == 1);
312 TEST_ASSERT_VAL("Unmatched total period for all filter",
313 hists->stats.total_non_filtered_period == 200);
314 }
315
316
317 err = TEST_OK;
318
319 out:
320 /* tear down everything */
321 perf_evlist__delete(evlist);
322 reset_output_field();
323 machines__exit(&machines);
324
325 return err;
326 }