Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 #include "util/debug.h"
0003 #include "util/map.h"
0004 #include "util/symbol.h"
0005 #include "util/sort.h"
0006 #include "util/evsel.h"
0007 #include "util/event.h"
0008 #include "util/evlist.h"
0009 #include "util/machine.h"
0010 #include "util/parse-events.h"
0011 #include "tests/tests.h"
0012 #include "tests/hists_common.h"
0013 #include <linux/kernel.h>
0014 
0015 struct sample {
0016     u32 pid;
0017     u64 ip;
0018     struct thread *thread;
0019     struct map *map;
0020     struct symbol *sym;
0021     int socket;
0022 };
0023 
0024 /* For the numbers, see hists_common.c */
0025 static struct sample fake_samples[] = {
0026     /* perf [kernel] schedule() */
0027     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 },
0028     /* perf [perf]   main() */
0029     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 },
0030     /* perf [libc]   malloc() */
0031     { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 },
0032     /* perf [perf]   main() */
0033     { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */
0034     /* perf [perf]   cmd_record() */
0035     { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 },
0036     /* perf [kernel] page_fault() */
0037     { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 },
0038     /* bash [bash]   main() */
0039     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_MAIN, .socket = 2 },
0040     /* bash [bash]   xmalloc() */
0041     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 },
0042     /* bash [libc]   malloc() */
0043     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 },
0044     /* bash [kernel] page_fault() */
0045     { .pid = FAKE_PID_BASH,  .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
0046 };
0047 
0048 static int add_hist_entries(struct evlist *evlist,
0049                 struct machine *machine)
0050 {
0051     struct evsel *evsel;
0052     struct addr_location al;
0053     struct perf_sample sample = { .period = 100, };
0054     size_t i;
0055 
0056     /*
0057      * each evsel will have 10 samples but the 4th sample
0058      * (perf [perf] main) will be collapsed to an existing entry
0059      * so total 9 entries will be in the tree.
0060      */
0061     evlist__for_each_entry(evlist, evsel) {
0062         for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
0063             struct hist_entry_iter iter = {
0064                 .evsel = evsel,
0065                 .sample = &sample,
0066                 .ops = &hist_iter_normal,
0067                 .hide_unresolved = false,
0068             };
0069             struct hists *hists = evsel__hists(evsel);
0070 
0071             /* make sure it has no filter at first */
0072             hists->thread_filter = NULL;
0073             hists->dso_filter = NULL;
0074             hists->symbol_filter_str = NULL;
0075 
0076             sample.cpumode = PERF_RECORD_MISC_USER;
0077             sample.pid = fake_samples[i].pid;
0078             sample.tid = fake_samples[i].pid;
0079             sample.ip = fake_samples[i].ip;
0080 
0081             if (machine__resolve(machine, &al, &sample) < 0)
0082                 goto out;
0083 
0084             al.socket = fake_samples[i].socket;
0085             if (hist_entry_iter__add(&iter, &al,
0086                          sysctl_perf_event_max_stack, NULL) < 0) {
0087                 addr_location__put(&al);
0088                 goto out;
0089             }
0090 
0091             fake_samples[i].thread = al.thread;
0092             fake_samples[i].map = al.map;
0093             fake_samples[i].sym = al.sym;
0094         }
0095     }
0096 
0097     return 0;
0098 
0099 out:
0100     pr_debug("Not enough memory for adding a hist entry\n");
0101     return TEST_FAIL;
0102 }
0103 
0104 static int test__hists_filter(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
0105 {
0106     int err = TEST_FAIL;
0107     struct machines machines;
0108     struct machine *machine;
0109     struct evsel *evsel;
0110     struct evlist *evlist = evlist__new();
0111 
0112     TEST_ASSERT_VAL("No memory", evlist);
0113 
0114     err = parse_event(evlist, "cpu-clock");
0115     if (err)
0116         goto out;
0117     err = parse_event(evlist, "task-clock");
0118     if (err)
0119         goto out;
0120     err = TEST_FAIL;
0121 
0122     /* default sort order (comm,dso,sym) will be used */
0123     if (setup_sorting(NULL) < 0)
0124         goto out;
0125 
0126     machines__init(&machines);
0127 
0128     /* setup threads/dso/map/symbols also */
0129     machine = setup_fake_machine(&machines);
0130     if (!machine)
0131         goto out;
0132 
0133     if (verbose > 1)
0134         machine__fprintf(machine, stderr);
0135 
0136     /* process sample events */
0137     err = add_hist_entries(evlist, machine);
0138     if (err < 0)
0139         goto out;
0140 
0141     evlist__for_each_entry(evlist, evsel) {
0142         struct hists *hists = evsel__hists(evsel);
0143 
0144         hists__collapse_resort(hists, NULL);
0145         evsel__output_resort(evsel, NULL);
0146 
0147         if (verbose > 2) {
0148             pr_info("Normal histogram\n");
0149             print_hists_out(hists);
0150         }
0151 
0152         TEST_ASSERT_VAL("Invalid nr samples",
0153                 hists->stats.nr_samples == 10);
0154         TEST_ASSERT_VAL("Invalid nr hist entries",
0155                 hists->nr_entries == 9);
0156         TEST_ASSERT_VAL("Invalid total period",
0157                 hists->stats.total_period == 1000);
0158         TEST_ASSERT_VAL("Unmatched nr samples",
0159                 hists->stats.nr_samples ==
0160                 hists->stats.nr_non_filtered_samples);
0161         TEST_ASSERT_VAL("Unmatched nr hist entries",
0162                 hists->nr_entries == hists->nr_non_filtered_entries);
0163         TEST_ASSERT_VAL("Unmatched total period",
0164                 hists->stats.total_period ==
0165                 hists->stats.total_non_filtered_period);
0166 
0167         /* now applying thread filter for 'bash' */
0168         hists->thread_filter = fake_samples[9].thread;
0169         hists__filter_by_thread(hists);
0170 
0171         if (verbose > 2) {
0172             pr_info("Histogram for thread filter\n");
0173             print_hists_out(hists);
0174         }
0175 
0176         /* normal stats should be invariant */
0177         TEST_ASSERT_VAL("Invalid nr samples",
0178                 hists->stats.nr_samples == 10);
0179         TEST_ASSERT_VAL("Invalid nr hist entries",
0180                 hists->nr_entries == 9);
0181         TEST_ASSERT_VAL("Invalid total period",
0182                 hists->stats.total_period == 1000);
0183 
0184         /* but filter stats are changed */
0185         TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
0186                 hists->stats.nr_non_filtered_samples == 4);
0187         TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
0188                 hists->nr_non_filtered_entries == 4);
0189         TEST_ASSERT_VAL("Unmatched total period for thread filter",
0190                 hists->stats.total_non_filtered_period == 400);
0191 
0192         /* remove thread filter first */
0193         hists->thread_filter = NULL;
0194         hists__filter_by_thread(hists);
0195 
0196         /* now applying dso filter for 'kernel' */
0197         hists->dso_filter = fake_samples[0].map->dso;
0198         hists__filter_by_dso(hists);
0199 
0200         if (verbose > 2) {
0201             pr_info("Histogram for dso filter\n");
0202             print_hists_out(hists);
0203         }
0204 
0205         /* normal stats should be invariant */
0206         TEST_ASSERT_VAL("Invalid nr samples",
0207                 hists->stats.nr_samples == 10);
0208         TEST_ASSERT_VAL("Invalid nr hist entries",
0209                 hists->nr_entries == 9);
0210         TEST_ASSERT_VAL("Invalid total period",
0211                 hists->stats.total_period == 1000);
0212 
0213         /* but filter stats are changed */
0214         TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
0215                 hists->stats.nr_non_filtered_samples == 3);
0216         TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
0217                 hists->nr_non_filtered_entries == 3);
0218         TEST_ASSERT_VAL("Unmatched total period for dso filter",
0219                 hists->stats.total_non_filtered_period == 300);
0220 
0221         /* remove dso filter first */
0222         hists->dso_filter = NULL;
0223         hists__filter_by_dso(hists);
0224 
0225         /*
0226          * now applying symbol filter for 'main'.  Also note that
0227          * there's 3 samples that have 'main' symbol but the 4th
0228          * entry of fake_samples was collapsed already so it won't
0229          * be counted as a separate entry but the sample count and
0230          * total period will be remained.
0231          */
0232         hists->symbol_filter_str = "main";
0233         hists__filter_by_symbol(hists);
0234 
0235         if (verbose > 2) {
0236             pr_info("Histogram for symbol filter\n");
0237             print_hists_out(hists);
0238         }
0239 
0240         /* normal stats should be invariant */
0241         TEST_ASSERT_VAL("Invalid nr samples",
0242                 hists->stats.nr_samples == 10);
0243         TEST_ASSERT_VAL("Invalid nr hist entries",
0244                 hists->nr_entries == 9);
0245         TEST_ASSERT_VAL("Invalid total period",
0246                 hists->stats.total_period == 1000);
0247 
0248         /* but filter stats are changed */
0249         TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
0250                 hists->stats.nr_non_filtered_samples == 3);
0251         TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
0252                 hists->nr_non_filtered_entries == 2);
0253         TEST_ASSERT_VAL("Unmatched total period for symbol filter",
0254                 hists->stats.total_non_filtered_period == 300);
0255 
0256         /* remove symbol filter first */
0257         hists->symbol_filter_str = NULL;
0258         hists__filter_by_symbol(hists);
0259 
0260         /* now applying socket filters */
0261         hists->socket_filter = 2;
0262         hists__filter_by_socket(hists);
0263 
0264         if (verbose > 2) {
0265             pr_info("Histogram for socket filters\n");
0266             print_hists_out(hists);
0267         }
0268 
0269         /* normal stats should be invariant */
0270         TEST_ASSERT_VAL("Invalid nr samples",
0271                 hists->stats.nr_samples == 10);
0272         TEST_ASSERT_VAL("Invalid nr hist entries",
0273                 hists->nr_entries == 9);
0274         TEST_ASSERT_VAL("Invalid total period",
0275                 hists->stats.total_period == 1000);
0276 
0277         /* but filter stats are changed */
0278         TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
0279                 hists->stats.nr_non_filtered_samples == 2);
0280         TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
0281                 hists->nr_non_filtered_entries == 2);
0282         TEST_ASSERT_VAL("Unmatched total period for socket filter",
0283                 hists->stats.total_non_filtered_period == 200);
0284 
0285         /* remove socket filter first */
0286         hists->socket_filter = -1;
0287         hists__filter_by_socket(hists);
0288 
0289         /* now applying all filters at once. */
0290         hists->thread_filter = fake_samples[1].thread;
0291         hists->dso_filter = fake_samples[1].map->dso;
0292         hists__filter_by_thread(hists);
0293         hists__filter_by_dso(hists);
0294 
0295         if (verbose > 2) {
0296             pr_info("Histogram for all filters\n");
0297             print_hists_out(hists);
0298         }
0299 
0300         /* normal stats should be invariant */
0301         TEST_ASSERT_VAL("Invalid nr samples",
0302                 hists->stats.nr_samples == 10);
0303         TEST_ASSERT_VAL("Invalid nr hist entries",
0304                 hists->nr_entries == 9);
0305         TEST_ASSERT_VAL("Invalid total period",
0306                 hists->stats.total_period == 1000);
0307 
0308         /* but filter stats are changed */
0309         TEST_ASSERT_VAL("Unmatched nr samples for all filter",
0310                 hists->stats.nr_non_filtered_samples == 2);
0311         TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
0312                 hists->nr_non_filtered_entries == 1);
0313         TEST_ASSERT_VAL("Unmatched total period for all filter",
0314                 hists->stats.total_non_filtered_period == 200);
0315     }
0316 
0317 
0318     err = TEST_OK;
0319 
0320 out:
0321     /* tear down everything */
0322     evlist__delete(evlist);
0323     reset_output_field();
0324     machines__exit(&machines);
0325 
0326     return err;
0327 }
0328 
0329 DEFINE_SUITE("Filter hist entries", hists_filter);