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