~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/tests/hists_filter.c

Version: ~ [ linux-6.2-rc3 ] ~ [ linux-6.1.5 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.87 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.162 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.228 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.269 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.302 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.302 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 // SPDX-License-Identifier: GPL-2.0
  2 #include "util/debug.h"
  3 #include "util/map.h"
  4 #include "util/symbol.h"
  5 #include "util/sort.h"
  6 #include "util/evsel.h"
  7 #include "util/event.h"
  8 #include "util/evlist.h"
  9 #include "util/machine.h"
 10 #include "util/parse-events.h"
 11 #include "tests/tests.h"
 12 #include "tests/hists_common.h"
 13 #include <linux/kernel.h>
 14 
 15 struct sample {
 16         u32 pid;
 17         u64 ip;
 18         struct thread *thread;
 19         struct map *map;
 20         struct symbol *sym;
 21         int socket;
 22 };
 23 
 24 /* For the numbers, see hists_common.c */
 25 static struct sample fake_samples[] = {
 26         /* perf [kernel] schedule() */
 27         { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 },
 28         /* perf [perf]   main() */
 29         { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 },
 30         /* perf [libc]   malloc() */
 31         { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 },
 32         /* perf [perf]   main() */
 33         { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */
 34         /* perf [perf]   cmd_record() */
 35         { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 },
 36         /* perf [kernel] page_fault() */
 37         { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 },
 38         /* bash [bash]   main() */
 39         { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_MAIN, .socket = 2 },
 40         /* bash [bash]   xmalloc() */
 41         { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 },
 42         /* bash [libc]   malloc() */
 43         { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 },
 44         /* bash [kernel] page_fault() */
 45         { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
 46 };
 47 
 48 static int add_hist_entries(struct evlist *evlist,
 49                             struct machine *machine)
 50 {
 51         struct evsel *evsel;
 52         struct addr_location al;
 53         struct perf_sample sample = { .period = 100, };
 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          */
 61         evlist__for_each_entry(evlist, evsel) {
 62                 for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
 63                         struct hist_entry_iter iter = {
 64                                 .evsel = evsel,
 65                                 .sample = &sample,
 66                                 .ops = &hist_iter_normal,
 67                                 .hide_unresolved = false,
 68                         };
 69                         struct hists *hists = evsel__hists(evsel);
 70 
 71                         /* make sure it has no filter at first */
 72                         hists->thread_filter = NULL;
 73                         hists->dso_filter = NULL;
 74                         hists->symbol_filter_str = NULL;
 75 
 76                         sample.cpumode = PERF_RECORD_MISC_USER;
 77                         sample.pid = fake_samples[i].pid;
 78                         sample.tid = fake_samples[i].pid;
 79                         sample.ip = fake_samples[i].ip;
 80 
 81                         if (machine__resolve(machine, &al, &sample) < 0)
 82                                 goto out;
 83 
 84                         al.socket = fake_samples[i].socket;
 85                         if (hist_entry_iter__add(&iter, &al,
 86                                                  sysctl_perf_event_max_stack, NULL) < 0) {
 87                                 addr_location__put(&al);
 88                                 goto out;
 89                         }
 90 
 91                         fake_samples[i].thread = al.thread;
 92                         fake_samples[i].map = al.map;
 93                         fake_samples[i].sym = al.sym;
 94                 }
 95         }
 96 
 97         return 0;
 98 
 99 out:
100         pr_debug("Not enough memory for adding a hist entry\n");
101         return TEST_FAIL;
102 }
103 
104 static int test__hists_filter(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
105 {
106         int err = TEST_FAIL;
107         struct machines machines;
108         struct machine *machine;
109         struct evsel *evsel;
110         struct evlist *evlist = evlist__new();
111 
112         TEST_ASSERT_VAL("No memory", evlist);
113 
114         err = parse_events(evlist, "cpu-clock", NULL);
115         if (err)
116                 goto out;
117         err = parse_events(evlist, "task-clock", NULL);
118         if (err)
119                 goto out;
120         err = TEST_FAIL;
121 
122         /* default sort order (comm,dso,sym) will be used */
123         if (setup_sorting(NULL) < 0)
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 
141         evlist__for_each_entry(evlist, evsel) {
142                 struct hists *hists = evsel__hists(evsel);
143 
144                 hists__collapse_resort(hists, NULL);
145                 evsel__output_resort(evsel, NULL);
146 
147                 if (verbose > 2) {
148                         pr_info("Normal histogram\n");
149                         print_hists_out(hists);
150                 }
151 
152                 TEST_ASSERT_VAL("Invalid nr samples",
153                                 hists->stats.nr_samples == 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_samples ==
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' */
168                 hists->thread_filter = fake_samples[9].thread;
169                 hists__filter_by_thread(hists);
170 
171                 if (verbose > 2) {
172                         pr_info("Histogram for thread filter\n");
173                         print_hists_out(hists);
174                 }
175 
176                 /* normal stats should be invariant */
177                 TEST_ASSERT_VAL("Invalid nr samples",
178                                 hists->stats.nr_samples == 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 */
193                 hists->thread_filter = NULL;
194                 hists__filter_by_thread(hists);
195 
196                 /* now applying dso filter for 'kernel' */
197                 hists->dso_filter = fake_samples[0].map->dso;
198                 hists__filter_by_dso(hists);
199 
200                 if (verbose > 2) {
201                         pr_info("Histogram for dso filter\n");
202                         print_hists_out(hists);
203                 }
204 
205                 /* normal stats should be invariant */
206                 TEST_ASSERT_VAL("Invalid nr samples",
207                                 hists->stats.nr_samples == 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 */
222                 hists->dso_filter = NULL;
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                  */
232                 hists->symbol_filter_str = "main";
233                 hists__filter_by_symbol(hists);
234 
235                 if (verbose > 2) {
236                         pr_info("Histogram for symbol filter\n");
237                         print_hists_out(hists);
238                 }
239 
240                 /* normal stats should be invariant */
241                 TEST_ASSERT_VAL("Invalid nr samples",
242                                 hists->stats.nr_samples == 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 
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_samples == 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 
289                 /* now applying all filters at once. */
290                 hists->thread_filter = fake_samples[1].thread;
291                 hists->dso_filter = fake_samples[1].map->dso;
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");
297                         print_hists_out(hists);
298                 }
299 
300                 /* normal stats should be invariant */
301                 TEST_ASSERT_VAL("Invalid nr samples",
302                                 hists->stats.nr_samples == 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 
320 out:
321         /* tear down everything */
322         evlist__delete(evlist);
323         reset_output_field();
324         machines__exit(&machines);
325 
326         return err;
327 }
328 
329 DEFINE_SUITE("Filter hist entries", hists_filter);
330 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp