diff options
-rw-r--r-- | tools/perf/Documentation/perf-record.txt | 6 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-report.txt | 2 | ||||
-rw-r--r-- | tools/perf/Documentation/perf-top.txt | 2 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-diff.c | 7 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 2 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 8 | ||||
-rw-r--r-- | tools/perf/builtin-top.c | 5 | ||||
-rw-r--r-- | tools/perf/perf.h | 1 | ||||
-rw-r--r-- | tools/perf/tests/hists_link.c | 4 | ||||
-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 |
17 files changed, 110 insertions, 22 deletions
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt index 938e8904f64d..d4da111ef53d 100644 --- a/tools/perf/Documentation/perf-record.txt +++ b/tools/perf/Documentation/perf-record.txt | |||
@@ -182,6 +182,12 @@ is enabled for all the sampling events. The sampled branch type is the same for | |||
182 | The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k | 182 | The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k |
183 | Note that this feature may not be available on all processors. | 183 | Note that this feature may not be available on all processors. |
184 | 184 | ||
185 | -W:: | ||
186 | --weight:: | ||
187 | Enable weightened sampling. An additional weight is recorded per sample and can be | ||
188 | displayed with the weight and local_weight sort keys. This currently works for TSX | ||
189 | abort events and some memory events in precise mode on modern Intel CPUs. | ||
190 | |||
185 | SEE ALSO | 191 | SEE ALSO |
186 | -------- | 192 | -------- |
187 | linkperf:perf-stat[1], linkperf:perf-list[1] | 193 | linkperf:perf-stat[1], linkperf:perf-list[1] |
diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt index 71f15510ca0b..7d5f4f38aa52 100644 --- a/tools/perf/Documentation/perf-report.txt +++ b/tools/perf/Documentation/perf-report.txt | |||
@@ -59,7 +59,7 @@ OPTIONS | |||
59 | --sort=:: | 59 | --sort=:: |
60 | Sort histogram entries by given key(s) - multiple keys can be specified | 60 | Sort histogram entries by given key(s) - multiple keys can be specified |
61 | in CSV format. Following sort keys are available: | 61 | in CSV format. Following sort keys are available: |
62 | pid, comm, dso, symbol, parent, cpu, srcline. | 62 | pid, comm, dso, symbol, parent, cpu, srcline, weight, local_weight. |
63 | 63 | ||
64 | Each key has following meaning: | 64 | Each key has following meaning: |
65 | 65 | ||
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt index a414bc95fd52..9f1a2fe54757 100644 --- a/tools/perf/Documentation/perf-top.txt +++ b/tools/perf/Documentation/perf-top.txt | |||
@@ -112,7 +112,7 @@ Default is to monitor all CPUS. | |||
112 | 112 | ||
113 | -s:: | 113 | -s:: |
114 | --sort:: | 114 | --sort:: |
115 | Sort by key(s): pid, comm, dso, symbol, parent, srcline. | 115 | Sort by key(s): pid, comm, dso, symbol, parent, srcline, weight, local_weight. |
116 | 116 | ||
117 | -n:: | 117 | -n:: |
118 | --show-nr-samples:: | 118 | --show-nr-samples:: |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index ae36f3cb5410..db491e9a812b 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -63,7 +63,7 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel, | |||
63 | return 0; | 63 | return 0; |
64 | } | 64 | } |
65 | 65 | ||
66 | he = __hists__add_entry(&evsel->hists, al, NULL, 1); | 66 | he = __hists__add_entry(&evsel->hists, al, NULL, 1, 1); |
67 | if (he == NULL) | 67 | if (he == NULL) |
68 | return -ENOMEM; | 68 | return -ENOMEM; |
69 | 69 | ||
diff --git a/tools/perf/builtin-diff.c b/tools/perf/builtin-diff.c index d207a97a2db1..2d0462d89a97 100644 --- a/tools/perf/builtin-diff.c +++ b/tools/perf/builtin-diff.c | |||
@@ -231,9 +231,10 @@ int perf_diff__formula(struct hist_entry *he, struct hist_entry *pair, | |||
231 | } | 231 | } |
232 | 232 | ||
233 | static int hists__add_entry(struct hists *self, | 233 | static int hists__add_entry(struct hists *self, |
234 | struct addr_location *al, u64 period) | 234 | struct addr_location *al, u64 period, |
235 | u64 weight) | ||
235 | { | 236 | { |
236 | if (__hists__add_entry(self, al, NULL, period) != NULL) | 237 | if (__hists__add_entry(self, al, NULL, period, weight) != NULL) |
237 | return 0; | 238 | return 0; |
238 | return -ENOMEM; | 239 | return -ENOMEM; |
239 | } | 240 | } |
@@ -255,7 +256,7 @@ static int diff__process_sample_event(struct perf_tool *tool __maybe_unused, | |||
255 | if (al.filtered) | 256 | if (al.filtered) |
256 | return 0; | 257 | return 0; |
257 | 258 | ||
258 | if (hists__add_entry(&evsel->hists, &al, sample->period)) { | 259 | if (hists__add_entry(&evsel->hists, &al, sample->period, sample->weight)) { |
259 | pr_warning("problem incrementing symbol period, skipping event\n"); | 260 | pr_warning("problem incrementing symbol period, skipping event\n"); |
260 | return -1; | 261 | return -1; |
261 | } | 262 | } |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 78a41fdbe56c..cdf58ecc04b1 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -953,6 +953,8 @@ const struct option record_options[] = { | |||
953 | OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, | 953 | OPT_CALLBACK('j', "branch-filter", &record.opts.branch_stack, |
954 | "branch filter mask", "branch stack filter modes", | 954 | "branch filter mask", "branch stack filter modes", |
955 | parse_branch_stack), | 955 | parse_branch_stack), |
956 | OPT_BOOLEAN('W', "weight", &record.opts.sample_weight, | ||
957 | "sample by weight (on special events only)"), | ||
956 | OPT_END() | 958 | OPT_END() |
957 | }; | 959 | }; |
958 | 960 | ||
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index b5ea26cc7eb1..e31f070abe2f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -98,7 +98,7 @@ static int perf_report__add_branch_hist_entry(struct perf_tool *tool, | |||
98 | * and not events sampled. Thus we use a pseudo period of 1. | 98 | * and not events sampled. Thus we use a pseudo period of 1. |
99 | */ | 99 | */ |
100 | he = __hists__add_branch_entry(&evsel->hists, al, parent, | 100 | he = __hists__add_branch_entry(&evsel->hists, al, parent, |
101 | &bi[i], 1); | 101 | &bi[i], 1, 1); |
102 | if (he) { | 102 | if (he) { |
103 | struct annotation *notes; | 103 | struct annotation *notes; |
104 | err = -ENOMEM; | 104 | err = -ENOMEM; |
@@ -156,7 +156,8 @@ static int perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
156 | return err; | 156 | return err; |
157 | } | 157 | } |
158 | 158 | ||
159 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period); | 159 | he = __hists__add_entry(&evsel->hists, al, parent, sample->period, |
160 | sample->weight); | ||
160 | if (he == NULL) | 161 | if (he == NULL) |
161 | return -ENOMEM; | 162 | return -ENOMEM; |
162 | 163 | ||
@@ -644,7 +645,8 @@ int cmd_report(int argc, const char **argv, const char *prefix __maybe_unused) | |||
644 | "Use the stdio interface"), | 645 | "Use the stdio interface"), |
645 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | 646 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", |
646 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," | 647 | "sort by key(s): pid, comm, dso, symbol, parent, cpu, srcline," |
647 | " dso_to, dso_from, symbol_to, symbol_from, mispredict"), | 648 | " dso_to, dso_from, symbol_to, symbol_from, mispredict," |
649 | " weight, local_weight"), | ||
648 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, | 650 | OPT_BOOLEAN(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, |
649 | "Show sample percentage for different cpu modes"), | 651 | "Show sample percentage for different cpu modes"), |
650 | OPT_STRING('p', "parent", &parent_pattern, "regex", | 652 | OPT_STRING('p', "parent", &parent_pattern, "regex", |
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c index b5520ad0dbb8..67bdb9f14ad6 100644 --- a/tools/perf/builtin-top.c +++ b/tools/perf/builtin-top.c | |||
@@ -251,7 +251,8 @@ static struct hist_entry *perf_evsel__add_hist_entry(struct perf_evsel *evsel, | |||
251 | { | 251 | { |
252 | struct hist_entry *he; | 252 | struct hist_entry *he; |
253 | 253 | ||
254 | he = __hists__add_entry(&evsel->hists, al, NULL, sample->period); | 254 | he = __hists__add_entry(&evsel->hists, al, NULL, sample->period, |
255 | sample->weight); | ||
255 | if (he == NULL) | 256 | if (he == NULL) |
256 | return NULL; | 257 | return NULL; |
257 | 258 | ||
@@ -1088,7 +1089,7 @@ int cmd_top(int argc, const char **argv, const char *prefix __maybe_unused) | |||
1088 | OPT_INCR('v', "verbose", &verbose, | 1089 | OPT_INCR('v', "verbose", &verbose, |
1089 | "be more verbose (show counter open errors, etc)"), | 1090 | "be more verbose (show counter open errors, etc)"), |
1090 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", | 1091 | OPT_STRING('s', "sort", &sort_order, "key[,key2...]", |
1091 | "sort by key(s): pid, comm, dso, symbol, parent"), | 1092 | "sort by key(s): pid, comm, dso, symbol, parent, weight, local_weight"), |
1092 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, | 1093 | OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples, |
1093 | "Show a column with the number of samples"), | 1094 | "Show a column with the number of samples"), |
1094 | OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, | 1095 | OPT_CALLBACK_DEFAULT('G', "call-graph", &top.record_opts, |
diff --git a/tools/perf/perf.h b/tools/perf/perf.h index 74659ecf93e0..32bd102c32b6 100644 --- a/tools/perf/perf.h +++ b/tools/perf/perf.h | |||
@@ -218,6 +218,7 @@ struct perf_record_opts { | |||
218 | bool pipe_output; | 218 | bool pipe_output; |
219 | bool raw_samples; | 219 | bool raw_samples; |
220 | bool sample_address; | 220 | bool sample_address; |
221 | bool sample_weight; | ||
221 | bool sample_time; | 222 | bool sample_time; |
222 | bool period; | 223 | bool period; |
223 | unsigned int freq; | 224 | unsigned int freq; |
diff --git a/tools/perf/tests/hists_link.c b/tools/perf/tests/hists_link.c index e0c0267858a1..89085a9615e2 100644 --- a/tools/perf/tests/hists_link.c +++ b/tools/perf/tests/hists_link.c | |||
@@ -223,7 +223,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
223 | &sample, 0) < 0) | 223 | &sample, 0) < 0) |
224 | goto out; | 224 | goto out; |
225 | 225 | ||
226 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1); | 226 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); |
227 | if (he == NULL) | 227 | if (he == NULL) |
228 | goto out; | 228 | goto out; |
229 | 229 | ||
@@ -247,7 +247,7 @@ static int add_hist_entries(struct perf_evlist *evlist, struct machine *machine) | |||
247 | &sample, 0) < 0) | 247 | &sample, 0) < 0) |
248 | goto out; | 248 | goto out; |
249 | 249 | ||
250 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1); | 250 | he = __hists__add_entry(&evsel->hists, &al, NULL, 1, 1); |
251 | if (he == NULL) | 251 | if (he == NULL) |
252 | goto out; | 252 | goto out; |
253 | 253 | ||
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, |