diff options
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/evsel.c | 10 | ||||
-rw-r--r-- | tools/perf/util/hist.c | 23 | ||||
-rw-r--r-- | tools/perf/util/hist.h | 8 | ||||
-rw-r--r-- | tools/perf/util/session.c | 3 | ||||
-rw-r--r-- | tools/perf/util/sort.c | 45 | ||||
-rw-r--r-- | tools/perf/util/sort.h | 3 |
7 files changed, 84 insertions, 9 deletions
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 0d573ff4771a..a97fbbe6b3b3 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -88,6 +88,7 @@ struct perf_sample { | |||
88 | u64 id; | 88 | u64 id; |
89 | u64 stream_id; | 89 | u64 stream_id; |
90 | u64 period; | 90 | u64 period; |
91 | u64 weight; | ||
91 | u32 cpu; | 92 | u32 cpu; |
92 | u32 raw_size; | 93 | u32 raw_size; |
93 | void *raw_data; | 94 | void *raw_data; |
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 1adb824610f0..23061a6ccd77 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c | |||
@@ -563,6 +563,9 @@ void perf_evsel__config(struct perf_evsel *evsel, | |||
563 | attr->branch_sample_type = opts->branch_stack; | 563 | attr->branch_sample_type = opts->branch_stack; |
564 | } | 564 | } |
565 | 565 | ||
566 | if (opts->sample_weight) | ||
567 | attr->sample_type |= PERF_SAMPLE_WEIGHT; | ||
568 | |||
566 | attr->mmap = track; | 569 | attr->mmap = track; |
567 | attr->comm = track; | 570 | attr->comm = track; |
568 | 571 | ||
@@ -1017,6 +1020,7 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
1017 | data->cpu = data->pid = data->tid = -1; | 1020 | data->cpu = data->pid = data->tid = -1; |
1018 | data->stream_id = data->id = data->time = -1ULL; | 1021 | data->stream_id = data->id = data->time = -1ULL; |
1019 | data->period = 1; | 1022 | data->period = 1; |
1023 | data->weight = 0; | ||
1020 | 1024 | ||
1021 | if (event->header.type != PERF_RECORD_SAMPLE) { | 1025 | if (event->header.type != PERF_RECORD_SAMPLE) { |
1022 | if (!evsel->attr.sample_id_all) | 1026 | if (!evsel->attr.sample_id_all) |
@@ -1167,6 +1171,12 @@ int perf_evsel__parse_sample(struct perf_evsel *evsel, union perf_event *event, | |||
1167 | } | 1171 | } |
1168 | } | 1172 | } |
1169 | 1173 | ||
1174 | data->weight = 0; | ||
1175 | if (type & PERF_SAMPLE_WEIGHT) { | ||
1176 | data->weight = *array; | ||
1177 | array++; | ||
1178 | } | ||
1179 | |||
1170 | return 0; | 1180 | return 0; |
1171 | } | 1181 | } |
1172 | 1182 | ||
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c index f855941bebea..97ddd18acd7c 100644 --- a/tools/perf/util/hist.c +++ b/tools/perf/util/hist.c | |||
@@ -155,9 +155,11 @@ static void hist_entry__add_cpumode_period(struct hist_entry *he, | |||
155 | } | 155 | } |
156 | } | 156 | } |
157 | 157 | ||
158 | static void he_stat__add_period(struct he_stat *he_stat, u64 period) | 158 | static void he_stat__add_period(struct he_stat *he_stat, u64 period, |
159 | u64 weight) | ||
159 | { | 160 | { |
160 | he_stat->period += period; | 161 | he_stat->period += period; |
162 | he_stat->weight += weight; | ||
161 | he_stat->nr_events += 1; | 163 | he_stat->nr_events += 1; |
162 | } | 164 | } |
163 | 165 | ||
@@ -169,12 +171,14 @@ static void he_stat__add_stat(struct he_stat *dest, struct he_stat *src) | |||
169 | dest->period_guest_sys += src->period_guest_sys; | 171 | dest->period_guest_sys += src->period_guest_sys; |
170 | dest->period_guest_us += src->period_guest_us; | 172 | dest->period_guest_us += src->period_guest_us; |
171 | dest->nr_events += src->nr_events; | 173 | dest->nr_events += src->nr_events; |
174 | dest->weight += src->weight; | ||
172 | } | 175 | } |
173 | 176 | ||
174 | static void hist_entry__decay(struct hist_entry *he) | 177 | static void hist_entry__decay(struct hist_entry *he) |
175 | { | 178 | { |
176 | he->stat.period = (he->stat.period * 7) / 8; | 179 | he->stat.period = (he->stat.period * 7) / 8; |
177 | he->stat.nr_events = (he->stat.nr_events * 7) / 8; | 180 | he->stat.nr_events = (he->stat.nr_events * 7) / 8; |
181 | /* XXX need decay for weight too? */ | ||
178 | } | 182 | } |
179 | 183 | ||
180 | static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) | 184 | static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) |
@@ -282,7 +286,8 @@ static u8 symbol__parent_filter(const struct symbol *parent) | |||
282 | static struct hist_entry *add_hist_entry(struct hists *hists, | 286 | static struct hist_entry *add_hist_entry(struct hists *hists, |
283 | struct hist_entry *entry, | 287 | struct hist_entry *entry, |
284 | struct addr_location *al, | 288 | struct addr_location *al, |
285 | u64 period) | 289 | u64 period, |
290 | u64 weight) | ||
286 | { | 291 | { |
287 | struct rb_node **p; | 292 | struct rb_node **p; |
288 | struct rb_node *parent = NULL; | 293 | struct rb_node *parent = NULL; |
@@ -306,7 +311,7 @@ static struct hist_entry *add_hist_entry(struct hists *hists, | |||
306 | cmp = hist_entry__cmp(he, entry); | 311 | cmp = hist_entry__cmp(he, entry); |
307 | 312 | ||
308 | if (!cmp) { | 313 | if (!cmp) { |
309 | he_stat__add_period(&he->stat, period); | 314 | he_stat__add_period(&he->stat, period, weight); |
310 | 315 | ||
311 | /* If the map of an existing hist_entry has | 316 | /* If the map of an existing hist_entry has |
312 | * become out-of-date due to an exec() or | 317 | * become out-of-date due to an exec() or |
@@ -345,7 +350,8 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, | |||
345 | struct addr_location *al, | 350 | struct addr_location *al, |
346 | struct symbol *sym_parent, | 351 | struct symbol *sym_parent, |
347 | struct branch_info *bi, | 352 | struct branch_info *bi, |
348 | u64 period) | 353 | u64 period, |
354 | u64 weight) | ||
349 | { | 355 | { |
350 | struct hist_entry entry = { | 356 | struct hist_entry entry = { |
351 | .thread = al->thread, | 357 | .thread = al->thread, |
@@ -359,6 +365,7 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, | |||
359 | .stat = { | 365 | .stat = { |
360 | .period = period, | 366 | .period = period, |
361 | .nr_events = 1, | 367 | .nr_events = 1, |
368 | .weight = weight, | ||
362 | }, | 369 | }, |
363 | .parent = sym_parent, | 370 | .parent = sym_parent, |
364 | .filtered = symbol__parent_filter(sym_parent), | 371 | .filtered = symbol__parent_filter(sym_parent), |
@@ -366,12 +373,13 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, | |||
366 | .hists = self, | 373 | .hists = self, |
367 | }; | 374 | }; |
368 | 375 | ||
369 | return add_hist_entry(self, &entry, al, period); | 376 | return add_hist_entry(self, &entry, al, period, weight); |
370 | } | 377 | } |
371 | 378 | ||
372 | struct hist_entry *__hists__add_entry(struct hists *self, | 379 | struct hist_entry *__hists__add_entry(struct hists *self, |
373 | struct addr_location *al, | 380 | struct addr_location *al, |
374 | struct symbol *sym_parent, u64 period) | 381 | struct symbol *sym_parent, u64 period, |
382 | u64 weight) | ||
375 | { | 383 | { |
376 | struct hist_entry entry = { | 384 | struct hist_entry entry = { |
377 | .thread = al->thread, | 385 | .thread = al->thread, |
@@ -385,13 +393,14 @@ struct hist_entry *__hists__add_entry(struct hists *self, | |||
385 | .stat = { | 393 | .stat = { |
386 | .period = period, | 394 | .period = period, |
387 | .nr_events = 1, | 395 | .nr_events = 1, |
396 | .weight = weight, | ||
388 | }, | 397 | }, |
389 | .parent = sym_parent, | 398 | .parent = sym_parent, |
390 | .filtered = symbol__parent_filter(sym_parent), | 399 | .filtered = symbol__parent_filter(sym_parent), |
391 | .hists = self, | 400 | .hists = self, |
392 | }; | 401 | }; |
393 | 402 | ||
394 | return add_hist_entry(self, &entry, al, period); | 403 | return add_hist_entry(self, &entry, al, period, weight); |
395 | } | 404 | } |
396 | 405 | ||
397 | int64_t | 406 | int64_t |
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h index 848331377bdb..121cc14b6041 100644 --- a/tools/perf/util/hist.h +++ b/tools/perf/util/hist.h | |||
@@ -49,6 +49,8 @@ enum hist_column { | |||
49 | HISTC_DSO_FROM, | 49 | HISTC_DSO_FROM, |
50 | HISTC_DSO_TO, | 50 | HISTC_DSO_TO, |
51 | HISTC_SRCLINE, | 51 | HISTC_SRCLINE, |
52 | HISTC_LOCAL_WEIGHT, | ||
53 | HISTC_GLOBAL_WEIGHT, | ||
52 | HISTC_NR_COLS, /* Last entry */ | 54 | HISTC_NR_COLS, /* Last entry */ |
53 | }; | 55 | }; |
54 | 56 | ||
@@ -73,7 +75,8 @@ struct hists { | |||
73 | 75 | ||
74 | struct hist_entry *__hists__add_entry(struct hists *self, | 76 | struct hist_entry *__hists__add_entry(struct hists *self, |
75 | struct addr_location *al, | 77 | struct addr_location *al, |
76 | struct symbol *parent, u64 period); | 78 | struct symbol *parent, u64 period, |
79 | u64 weight); | ||
77 | int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); | 80 | int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); |
78 | int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); | 81 | int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); |
79 | int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, | 82 | int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, |
@@ -84,7 +87,8 @@ struct hist_entry *__hists__add_branch_entry(struct hists *self, | |||
84 | struct addr_location *al, | 87 | struct addr_location *al, |
85 | struct symbol *sym_parent, | 88 | struct symbol *sym_parent, |
86 | struct branch_info *bi, | 89 | struct branch_info *bi, |
87 | u64 period); | 90 | u64 period, |
91 | u64 weight); | ||
88 | 92 | ||
89 | void hists__output_resort(struct hists *self); | 93 | void hists__output_resort(struct hists *self); |
90 | void hists__output_resort_threaded(struct hists *hists); | 94 | void hists__output_resort_threaded(struct hists *hists); |
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c index c8ba120b0dbe..627be09b479e 100644 --- a/tools/perf/util/session.c +++ b/tools/perf/util/session.c | |||
@@ -798,6 +798,9 @@ static void dump_sample(struct perf_evsel *evsel, union perf_event *event, | |||
798 | 798 | ||
799 | if (sample_type & PERF_SAMPLE_STACK_USER) | 799 | if (sample_type & PERF_SAMPLE_STACK_USER) |
800 | stack_user__printf(&sample->user_stack); | 800 | stack_user__printf(&sample->user_stack); |
801 | |||
802 | if (sample_type & PERF_SAMPLE_WEIGHT) | ||
803 | printf("... weight: %" PRIu64 "\n", sample->weight); | ||
801 | } | 804 | } |
802 | 805 | ||
803 | static struct machine * | 806 | static struct machine * |
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c index d41926cb9e3f..d66bcd33248c 100644 --- a/tools/perf/util/sort.c +++ b/tools/perf/util/sort.c | |||
@@ -464,6 +464,49 @@ struct sort_entry sort_mispredict = { | |||
464 | .se_width_idx = HISTC_MISPREDICT, | 464 | .se_width_idx = HISTC_MISPREDICT, |
465 | }; | 465 | }; |
466 | 466 | ||
467 | static u64 he_weight(struct hist_entry *he) | ||
468 | { | ||
469 | return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0; | ||
470 | } | ||
471 | |||
472 | static int64_t | ||
473 | sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right) | ||
474 | { | ||
475 | return he_weight(left) - he_weight(right); | ||
476 | } | ||
477 | |||
478 | static int hist_entry__local_weight_snprintf(struct hist_entry *self, char *bf, | ||
479 | size_t size, unsigned int width) | ||
480 | { | ||
481 | return repsep_snprintf(bf, size, "%-*llu", width, he_weight(self)); | ||
482 | } | ||
483 | |||
484 | struct sort_entry sort_local_weight = { | ||
485 | .se_header = "Local Weight", | ||
486 | .se_cmp = sort__local_weight_cmp, | ||
487 | .se_snprintf = hist_entry__local_weight_snprintf, | ||
488 | .se_width_idx = HISTC_LOCAL_WEIGHT, | ||
489 | }; | ||
490 | |||
491 | static int64_t | ||
492 | sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right) | ||
493 | { | ||
494 | return left->stat.weight - right->stat.weight; | ||
495 | } | ||
496 | |||
497 | static int hist_entry__global_weight_snprintf(struct hist_entry *self, char *bf, | ||
498 | size_t size, unsigned int width) | ||
499 | { | ||
500 | return repsep_snprintf(bf, size, "%-*llu", width, self->stat.weight); | ||
501 | } | ||
502 | |||
503 | struct sort_entry sort_global_weight = { | ||
504 | .se_header = "Weight", | ||
505 | .se_cmp = sort__global_weight_cmp, | ||
506 | .se_snprintf = hist_entry__global_weight_snprintf, | ||
507 | .se_width_idx = HISTC_GLOBAL_WEIGHT, | ||
508 | }; | ||
509 | |||
467 | struct sort_dimension { | 510 | struct sort_dimension { |
468 | const char *name; | 511 | const char *name; |
469 | struct sort_entry *entry; | 512 | struct sort_entry *entry; |
@@ -480,6 +523,8 @@ static struct sort_dimension common_sort_dimensions[] = { | |||
480 | DIM(SORT_PARENT, "parent", sort_parent), | 523 | DIM(SORT_PARENT, "parent", sort_parent), |
481 | DIM(SORT_CPU, "cpu", sort_cpu), | 524 | DIM(SORT_CPU, "cpu", sort_cpu), |
482 | DIM(SORT_SRCLINE, "srcline", sort_srcline), | 525 | DIM(SORT_SRCLINE, "srcline", sort_srcline), |
526 | DIM(SORT_LOCAL_WEIGHT, "local_weight", sort_local_weight), | ||
527 | DIM(SORT_GLOBAL_WEIGHT, "weight", sort_global_weight), | ||
483 | }; | 528 | }; |
484 | 529 | ||
485 | #undef DIM | 530 | #undef DIM |
diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h index b13e56f6ccbe..393925012796 100644 --- a/tools/perf/util/sort.h +++ b/tools/perf/util/sort.h | |||
@@ -49,6 +49,7 @@ struct he_stat { | |||
49 | u64 period_us; | 49 | u64 period_us; |
50 | u64 period_guest_sys; | 50 | u64 period_guest_sys; |
51 | u64 period_guest_us; | 51 | u64 period_guest_us; |
52 | u64 weight; | ||
52 | u32 nr_events; | 53 | u32 nr_events; |
53 | }; | 54 | }; |
54 | 55 | ||
@@ -130,6 +131,8 @@ enum sort_type { | |||
130 | SORT_PARENT, | 131 | SORT_PARENT, |
131 | SORT_CPU, | 132 | SORT_CPU, |
132 | SORT_SRCLINE, | 133 | SORT_SRCLINE, |
134 | SORT_LOCAL_WEIGHT, | ||
135 | SORT_GLOBAL_WEIGHT, | ||
133 | 136 | ||
134 | /* branch stack specific sort keys */ | 137 | /* branch stack specific sort keys */ |
135 | __SORT_BRANCH_STACK, | 138 | __SORT_BRANCH_STACK, |