123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- #include "perf.h"
- #include "util/debug.h"
- #include "util/symbol.h"
- #include "util/sort.h"
- #include "util/evsel.h"
- #include "util/evlist.h"
- #include "util/machine.h"
- #include "util/thread.h"
- #include "util/parse-events.h"
- #include "tests/tests.h"
- #include "tests/hists_common.h"
- struct sample {
- u32 pid;
- u64 ip;
- struct thread *thread;
- struct map *map;
- struct symbol *sym;
- int socket;
- };
- /* For the numbers, see hists_common.c */
- static struct sample fake_samples[] = {
- /* perf [kernel] schedule() */
- { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_KERNEL_SCHEDULE, .socket = 0 },
- /* perf [perf] main() */
- { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_PERF_MAIN, .socket = 0 },
- /* perf [libc] malloc() */
- { .pid = FAKE_PID_PERF1, .ip = FAKE_IP_LIBC_MALLOC, .socket = 0 },
- /* perf [perf] main() */
- { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_MAIN, .socket = 0 }, /* will be merged */
- /* perf [perf] cmd_record() */
- { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_PERF_CMD_RECORD, .socket = 1 },
- /* perf [kernel] page_fault() */
- { .pid = FAKE_PID_PERF2, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 1 },
- /* bash [bash] main() */
- { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_MAIN, .socket = 2 },
- /* bash [bash] xmalloc() */
- { .pid = FAKE_PID_BASH, .ip = FAKE_IP_BASH_XMALLOC, .socket = 2 },
- /* bash [libc] malloc() */
- { .pid = FAKE_PID_BASH, .ip = FAKE_IP_LIBC_MALLOC, .socket = 3 },
- /* bash [kernel] page_fault() */
- { .pid = FAKE_PID_BASH, .ip = FAKE_IP_KERNEL_PAGE_FAULT, .socket = 3 },
- };
- static int add_hist_entries(struct perf_evlist *evlist,
- struct machine *machine)
- {
- struct perf_evsel *evsel;
- struct addr_location al;
- struct perf_sample sample = { .period = 100, };
- size_t i;
- /*
- * each evsel will have 10 samples but the 4th sample
- * (perf [perf] main) will be collapsed to an existing entry
- * so total 9 entries will be in the tree.
- */
- evlist__for_each(evlist, evsel) {
- for (i = 0; i < ARRAY_SIZE(fake_samples); i++) {
- const union perf_event event = {
- .header = {
- .misc = PERF_RECORD_MISC_USER,
- },
- };
- struct hist_entry_iter iter = {
- .evsel = evsel,
- .sample = &sample,
- .ops = &hist_iter_normal,
- .hide_unresolved = false,
- };
- struct hists *hists = evsel__hists(evsel);
- /* make sure it has no filter at first */
- hists->thread_filter = NULL;
- hists->dso_filter = NULL;
- hists->symbol_filter_str = NULL;
- sample.pid = fake_samples[i].pid;
- sample.tid = fake_samples[i].pid;
- sample.ip = fake_samples[i].ip;
- if (perf_event__preprocess_sample(&event, machine, &al,
- &sample) < 0)
- goto out;
- al.socket = fake_samples[i].socket;
- if (hist_entry_iter__add(&iter, &al,
- PERF_MAX_STACK_DEPTH, NULL) < 0) {
- addr_location__put(&al);
- goto out;
- }
- fake_samples[i].thread = al.thread;
- fake_samples[i].map = al.map;
- fake_samples[i].sym = al.sym;
- }
- }
- return 0;
- out:
- pr_debug("Not enough memory for adding a hist entry\n");
- return TEST_FAIL;
- }
- int test__hists_filter(void)
- {
- int err = TEST_FAIL;
- struct machines machines;
- struct machine *machine;
- struct perf_evsel *evsel;
- struct perf_evlist *evlist = perf_evlist__new();
- TEST_ASSERT_VAL("No memory", evlist);
- err = parse_events(evlist, "cpu-clock", NULL);
- if (err)
- goto out;
- err = parse_events(evlist, "task-clock", NULL);
- if (err)
- goto out;
- /* default sort order (comm,dso,sym) will be used */
- if (setup_sorting() < 0)
- goto out;
- machines__init(&machines);
- /* setup threads/dso/map/symbols also */
- machine = setup_fake_machine(&machines);
- if (!machine)
- goto out;
- if (verbose > 1)
- machine__fprintf(machine, stderr);
- /* process sample events */
- err = add_hist_entries(evlist, machine);
- if (err < 0)
- goto out;
- evlist__for_each(evlist, evsel) {
- struct hists *hists = evsel__hists(evsel);
- hists__collapse_resort(hists, NULL);
- hists__output_resort(hists, NULL);
- if (verbose > 2) {
- pr_info("Normal histogram\n");
- print_hists_out(hists);
- }
- TEST_ASSERT_VAL("Invalid nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
- TEST_ASSERT_VAL("Invalid nr hist entries",
- hists->nr_entries == 9);
- TEST_ASSERT_VAL("Invalid total period",
- hists->stats.total_period == 1000);
- TEST_ASSERT_VAL("Unmatched nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] ==
- hists->stats.nr_non_filtered_samples);
- TEST_ASSERT_VAL("Unmatched nr hist entries",
- hists->nr_entries == hists->nr_non_filtered_entries);
- TEST_ASSERT_VAL("Unmatched total period",
- hists->stats.total_period ==
- hists->stats.total_non_filtered_period);
- /* now applying thread filter for 'bash' */
- hists->thread_filter = fake_samples[9].thread;
- hists__filter_by_thread(hists);
- if (verbose > 2) {
- pr_info("Histogram for thread filter\n");
- print_hists_out(hists);
- }
- /* normal stats should be invariant */
- TEST_ASSERT_VAL("Invalid nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
- TEST_ASSERT_VAL("Invalid nr hist entries",
- hists->nr_entries == 9);
- TEST_ASSERT_VAL("Invalid total period",
- hists->stats.total_period == 1000);
- /* but filter stats are changed */
- TEST_ASSERT_VAL("Unmatched nr samples for thread filter",
- hists->stats.nr_non_filtered_samples == 4);
- TEST_ASSERT_VAL("Unmatched nr hist entries for thread filter",
- hists->nr_non_filtered_entries == 4);
- TEST_ASSERT_VAL("Unmatched total period for thread filter",
- hists->stats.total_non_filtered_period == 400);
- /* remove thread filter first */
- hists->thread_filter = NULL;
- hists__filter_by_thread(hists);
- /* now applying dso filter for 'kernel' */
- hists->dso_filter = fake_samples[0].map->dso;
- hists__filter_by_dso(hists);
- if (verbose > 2) {
- pr_info("Histogram for dso filter\n");
- print_hists_out(hists);
- }
- /* normal stats should be invariant */
- TEST_ASSERT_VAL("Invalid nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
- TEST_ASSERT_VAL("Invalid nr hist entries",
- hists->nr_entries == 9);
- TEST_ASSERT_VAL("Invalid total period",
- hists->stats.total_period == 1000);
- /* but filter stats are changed */
- TEST_ASSERT_VAL("Unmatched nr samples for dso filter",
- hists->stats.nr_non_filtered_samples == 3);
- TEST_ASSERT_VAL("Unmatched nr hist entries for dso filter",
- hists->nr_non_filtered_entries == 3);
- TEST_ASSERT_VAL("Unmatched total period for dso filter",
- hists->stats.total_non_filtered_period == 300);
- /* remove dso filter first */
- hists->dso_filter = NULL;
- hists__filter_by_dso(hists);
- /*
- * now applying symbol filter for 'main'. Also note that
- * there's 3 samples that have 'main' symbol but the 4th
- * entry of fake_samples was collapsed already so it won't
- * be counted as a separate entry but the sample count and
- * total period will be remained.
- */
- hists->symbol_filter_str = "main";
- hists__filter_by_symbol(hists);
- if (verbose > 2) {
- pr_info("Histogram for symbol filter\n");
- print_hists_out(hists);
- }
- /* normal stats should be invariant */
- TEST_ASSERT_VAL("Invalid nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
- TEST_ASSERT_VAL("Invalid nr hist entries",
- hists->nr_entries == 9);
- TEST_ASSERT_VAL("Invalid total period",
- hists->stats.total_period == 1000);
- /* but filter stats are changed */
- TEST_ASSERT_VAL("Unmatched nr samples for symbol filter",
- hists->stats.nr_non_filtered_samples == 3);
- TEST_ASSERT_VAL("Unmatched nr hist entries for symbol filter",
- hists->nr_non_filtered_entries == 2);
- TEST_ASSERT_VAL("Unmatched total period for symbol filter",
- hists->stats.total_non_filtered_period == 300);
- /* remove symbol filter first */
- hists->symbol_filter_str = NULL;
- hists__filter_by_symbol(hists);
- /* now applying socket filters */
- hists->socket_filter = 2;
- hists__filter_by_socket(hists);
- if (verbose > 2) {
- pr_info("Histogram for socket filters\n");
- print_hists_out(hists);
- }
- /* normal stats should be invariant */
- TEST_ASSERT_VAL("Invalid nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
- TEST_ASSERT_VAL("Invalid nr hist entries",
- hists->nr_entries == 9);
- TEST_ASSERT_VAL("Invalid total period",
- hists->stats.total_period == 1000);
- /* but filter stats are changed */
- TEST_ASSERT_VAL("Unmatched nr samples for socket filter",
- hists->stats.nr_non_filtered_samples == 2);
- TEST_ASSERT_VAL("Unmatched nr hist entries for socket filter",
- hists->nr_non_filtered_entries == 2);
- TEST_ASSERT_VAL("Unmatched total period for socket filter",
- hists->stats.total_non_filtered_period == 200);
- /* remove socket filter first */
- hists->socket_filter = -1;
- hists__filter_by_socket(hists);
- /* now applying all filters at once. */
- hists->thread_filter = fake_samples[1].thread;
- hists->dso_filter = fake_samples[1].map->dso;
- hists__filter_by_thread(hists);
- hists__filter_by_dso(hists);
- if (verbose > 2) {
- pr_info("Histogram for all filters\n");
- print_hists_out(hists);
- }
- /* normal stats should be invariant */
- TEST_ASSERT_VAL("Invalid nr samples",
- hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10);
- TEST_ASSERT_VAL("Invalid nr hist entries",
- hists->nr_entries == 9);
- TEST_ASSERT_VAL("Invalid total period",
- hists->stats.total_period == 1000);
- /* but filter stats are changed */
- TEST_ASSERT_VAL("Unmatched nr samples for all filter",
- hists->stats.nr_non_filtered_samples == 2);
- TEST_ASSERT_VAL("Unmatched nr hist entries for all filter",
- hists->nr_non_filtered_entries == 1);
- TEST_ASSERT_VAL("Unmatched total period for all filter",
- hists->stats.total_non_filtered_period == 200);
- }
- err = TEST_OK;
- out:
- /* tear down everything */
- perf_evlist__delete(evlist);
- reset_output_field();
- machines__exit(&machines);
- return err;
- }
|