root/tools/perf/tests/hists_filter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. add_hist_entries
  2. test__hists_filter

   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 int test__hists_filter(struct test *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                 perf_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_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' */
 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_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 */
 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_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 */
 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_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 
 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 
 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_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 
 320 out:
 321         /* tear down everything */
 322         evlist__delete(evlist);
 323         reset_output_field();
 324         machines__exit(&machines);
 325 
 326         return err;
 327 }

/* [<][>][^][v][top][bottom][index][help] */