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