Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf hists: Split hists_stats from events_stats

Each struct hists have events_stats but most of the fields were not
used. It's to count number of samples and periods whether filtered or
not. And other fields are used only by evlist.

So it'd be better to split hists_stats and events_stats to reduce
wasted memory in the struct hists. This makes the output of event
statistics in the perf report compact by skipping 0 events in each
evsel/hists.

Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Link: https://lore.kernel.org/r/20210427013717.1651674-3-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
0f0abbac bf8f8587

+42 -29
+1 -1
tools/perf/builtin-annotate.c
··· 418 418 total_nr_samples = 0; 419 419 evlist__for_each_entry(session->evlist, pos) { 420 420 struct hists *hists = evsel__hists(pos); 421 - u32 nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 421 + u32 nr_samples = hists->stats.nr_samples; 422 422 423 423 if (nr_samples > 0) { 424 424 total_nr_samples += nr_samples;
+2 -2
tools/perf/builtin-report.c
··· 436 436 { 437 437 size_t ret; 438 438 char unit; 439 - unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 439 + unsigned long nr_samples = hists->stats.nr_samples; 440 440 u64 nr_events = hists->stats.total_period; 441 441 struct evsel *evsel = hists_to_evsel(hists); 442 442 char buf[512]; ··· 464 464 nr_samples += pos_hists->stats.nr_non_filtered_samples; 465 465 nr_events += pos_hists->stats.total_non_filtered_period; 466 466 } else { 467 - nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 467 + nr_samples += pos_hists->stats.nr_samples; 468 468 nr_events += pos_hists->stats.total_period; 469 469 } 470 470 }
+7 -7
tools/perf/tests/hists_filter.c
··· 150 150 } 151 151 152 152 TEST_ASSERT_VAL("Invalid nr samples", 153 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); 153 + hists->stats.nr_samples == 10); 154 154 TEST_ASSERT_VAL("Invalid nr hist entries", 155 155 hists->nr_entries == 9); 156 156 TEST_ASSERT_VAL("Invalid total period", 157 157 hists->stats.total_period == 1000); 158 158 TEST_ASSERT_VAL("Unmatched nr samples", 159 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 159 + hists->stats.nr_samples == 160 160 hists->stats.nr_non_filtered_samples); 161 161 TEST_ASSERT_VAL("Unmatched nr hist entries", 162 162 hists->nr_entries == hists->nr_non_filtered_entries); ··· 175 175 176 176 /* normal stats should be invariant */ 177 177 TEST_ASSERT_VAL("Invalid nr samples", 178 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); 178 + hists->stats.nr_samples == 10); 179 179 TEST_ASSERT_VAL("Invalid nr hist entries", 180 180 hists->nr_entries == 9); 181 181 TEST_ASSERT_VAL("Invalid total period", ··· 204 204 205 205 /* normal stats should be invariant */ 206 206 TEST_ASSERT_VAL("Invalid nr samples", 207 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); 207 + hists->stats.nr_samples == 10); 208 208 TEST_ASSERT_VAL("Invalid nr hist entries", 209 209 hists->nr_entries == 9); 210 210 TEST_ASSERT_VAL("Invalid total period", ··· 239 239 240 240 /* normal stats should be invariant */ 241 241 TEST_ASSERT_VAL("Invalid nr samples", 242 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); 242 + hists->stats.nr_samples == 10); 243 243 TEST_ASSERT_VAL("Invalid nr hist entries", 244 244 hists->nr_entries == 9); 245 245 TEST_ASSERT_VAL("Invalid total period", ··· 268 268 269 269 /* normal stats should be invariant */ 270 270 TEST_ASSERT_VAL("Invalid nr samples", 271 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); 271 + hists->stats.nr_samples == 10); 272 272 TEST_ASSERT_VAL("Invalid nr hist entries", 273 273 hists->nr_entries == 9); 274 274 TEST_ASSERT_VAL("Invalid total period", ··· 299 299 300 300 /* normal stats should be invariant */ 301 301 TEST_ASSERT_VAL("Invalid nr samples", 302 - hists->stats.nr_events[PERF_RECORD_SAMPLE] == 10); 302 + hists->stats.nr_samples == 10); 303 303 TEST_ASSERT_VAL("Invalid nr hist entries", 304 304 hists->nr_entries == 9); 305 305 TEST_ASSERT_VAL("Invalid total period",
+9 -8
tools/perf/ui/browsers/hists.c
··· 682 682 switch (key) { 683 683 case K_TIMER: { 684 684 struct hist_browser_timer *hbt = browser->hbt; 685 + struct evsel *evsel = hists_to_evsel(browser->hists); 685 686 u64 nr_entries; 686 687 687 688 WARN_ON_ONCE(!hbt); ··· 697 696 ui_browser__update_nr_entries(&browser->b, nr_entries); 698 697 699 698 if (warn_lost_event && 700 - (browser->hists->stats.nr_lost_warned != 701 - browser->hists->stats.nr_events[PERF_RECORD_LOST])) { 702 - browser->hists->stats.nr_lost_warned = 703 - browser->hists->stats.nr_events[PERF_RECORD_LOST]; 699 + (evsel->evlist->stats.nr_lost_warned != 700 + evsel->evlist->stats.nr_events[PERF_RECORD_LOST])) { 701 + evsel->evlist->stats.nr_lost_warned = 702 + evsel->evlist->stats.nr_events[PERF_RECORD_LOST]; 704 703 ui_browser__warn_lost_events(&browser->b); 705 704 } 706 705 ··· 3417 3416 struct evsel *evsel = list_entry(entry, struct evsel, core.node); 3418 3417 struct hists *hists = evsel__hists(evsel); 3419 3418 bool current_entry = ui_browser__is_current_entry(browser, row); 3420 - unsigned long nr_events = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 3419 + unsigned long nr_events = hists->stats.nr_samples; 3421 3420 const char *ev_name = evsel__name(evsel); 3422 3421 char bf[256], unit; 3423 3422 const char *warn = " "; ··· 3433 3432 3434 3433 for_each_group_member(pos, evsel) { 3435 3434 struct hists *pos_hists = evsel__hists(pos); 3436 - nr_events += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 3435 + nr_events += pos_hists->stats.nr_samples; 3437 3436 } 3438 3437 } 3439 3438 ··· 3442 3441 unit, unit == ' ' ? "" : " ", ev_name); 3443 3442 ui_browser__printf(browser, "%s", bf); 3444 3443 3445 - nr_events = hists->stats.nr_events[PERF_RECORD_LOST]; 3444 + nr_events = evsel->evlist->stats.nr_events[PERF_RECORD_LOST]; 3446 3445 if (nr_events != 0) { 3447 3446 menu->lost_events = true; 3448 3447 if (!current_entry) ··· 3648 3647 { 3649 3648 struct hists *hists = evsel__hists(browser->block_evsel); 3650 3649 const char *evname = evsel__name(browser->block_evsel); 3651 - unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 3650 + unsigned long nr_samples = hists->stats.nr_samples; 3652 3651 int ret; 3653 3652 3654 3653 ret = scnprintf(bf, size, "# Samples: %lu", nr_samples);
+7 -3
tools/perf/util/events_stats.h
··· 26 26 * perf_record_sample.period and stash the result in total_period. 27 27 */ 28 28 struct events_stats { 29 - u64 total_period; 30 - u64 total_non_filtered_period; 31 29 u64 total_lost; 32 30 u64 total_lost_samples; 33 31 u64 total_aux_lost; 34 32 u64 total_aux_partial; 35 33 u64 total_invalid_chains; 36 34 u32 nr_events[PERF_RECORD_HEADER_MAX]; 37 - u32 nr_non_filtered_samples; 38 35 u32 nr_lost_warned; 39 36 u32 nr_unknown_events; 40 37 u32 nr_invalid_chains; ··· 39 42 u32 nr_unprocessable_samples; 40 43 u32 nr_auxtrace_errors[PERF_AUXTRACE_ERROR_MAX]; 41 44 u32 nr_proc_map_timeout; 45 + }; 46 + 47 + struct hists_stats { 48 + u64 total_period; 49 + u64 total_non_filtered_period; 50 + u32 nr_samples; 51 + u32 nr_non_filtered_samples; 42 52 }; 43 53 44 54 void events_stats__inc(struct events_stats *stats, u32 type);
+14 -6
tools/perf/util/hist.c
··· 2325 2325 ++stats->nr_events[type]; 2326 2326 } 2327 2327 2328 - void hists__inc_nr_events(struct hists *hists, u32 type) 2328 + static void hists_stats__inc(struct hists_stats *stats) 2329 2329 { 2330 - events_stats__inc(&hists->stats, type); 2330 + ++stats->nr_samples; 2331 + } 2332 + 2333 + void hists__inc_nr_events(struct hists *hists) 2334 + { 2335 + hists_stats__inc(&hists->stats); 2331 2336 } 2332 2337 2333 2338 void hists__inc_nr_samples(struct hists *hists, bool filtered) 2334 2339 { 2335 - events_stats__inc(&hists->stats, PERF_RECORD_SAMPLE); 2340 + hists_stats__inc(&hists->stats); 2336 2341 if (!filtered) 2337 2342 hists->stats.nr_non_filtered_samples++; 2338 2343 } ··· 2682 2677 size_t ret = 0; 2683 2678 2684 2679 evlist__for_each_entry(evlist, pos) { 2680 + struct hists *hists = evsel__hists(pos); 2681 + 2685 2682 ret += fprintf(fp, "%s stats:\n", evsel__name(pos)); 2686 - ret += events_stats__fprintf(&evsel__hists(pos)->stats, fp); 2683 + ret += fprintf(fp, "%16s events: %10d\n", 2684 + "SAMPLE", hists->stats.nr_samples); 2687 2685 } 2688 2686 2689 2687 return ret; ··· 2706 2698 const struct dso *dso = hists->dso_filter; 2707 2699 struct thread *thread = hists->thread_filter; 2708 2700 int socket_id = hists->socket_filter; 2709 - unsigned long nr_samples = hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2701 + unsigned long nr_samples = hists->stats.nr_samples; 2710 2702 u64 nr_events = hists->stats.total_period; 2711 2703 struct evsel *evsel = hists_to_evsel(hists); 2712 2704 const char *ev_name = evsel__name(evsel); ··· 2733 2725 nr_samples += pos_hists->stats.nr_non_filtered_samples; 2734 2726 nr_events += pos_hists->stats.total_non_filtered_period; 2735 2727 } else { 2736 - nr_samples += pos_hists->stats.nr_events[PERF_RECORD_SAMPLE]; 2728 + nr_samples += pos_hists->stats.nr_samples; 2737 2729 nr_events += pos_hists->stats.total_period; 2738 2730 } 2739 2731 }
+2 -2
tools/perf/util/hist.h
··· 96 96 const char *uid_filter_str; 97 97 const char *symbol_filter_str; 98 98 pthread_mutex_t lock; 99 - struct events_stats stats; 99 + struct hists_stats stats; 100 100 u64 event_stream; 101 101 u16 col_len[HISTC_NR_COLS]; 102 102 bool has_callchains; ··· 196 196 u64 hists__total_period(struct hists *hists); 197 197 void hists__reset_stats(struct hists *hists); 198 198 void hists__inc_stats(struct hists *hists, struct hist_entry *h); 199 - void hists__inc_nr_events(struct hists *hists, u32 type); 199 + void hists__inc_nr_events(struct hists *hists); 200 200 void hists__inc_nr_samples(struct hists *hists, bool filtered); 201 201 202 202 size_t hists__fprintf(struct hists *hists, bool show_header, int max_rows,