aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2013-01-24 10:10:29 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-04-01 11:19:43 -0400
commit05484298cbfebbf8c8c55b000541a245bc286bec (patch)
tree1b1336957d96defc9e637faf14aebacb5b9b693a /tools
parent2fe85427e3bf65d791700d065132772fc26e4d75 (diff)
perf tools: Add support for weight v7 (modified)
perf record has a new option -W that enables weightened sampling. Add sorting support in top/report for the average weight per sample and the total weight sum. This allows to both compare relative cost per event and the total cost over the measurement period. Add the necessary glue to perf report, record and the library. v2: Merge with new hist refactoring. v3: Fix manpage. Remove value check. Rename global_weight to weight and weight to local_weight. v4: Readd sort keys to manpage v5: Move weight to end v6: Move weight to template v7: Rename weight key. Original patch from Andi modified by Stephane Eranian <eranian@google.com> to include ONLY the weight supporting code and apply to pristine 3.8.0-rc4. Signed-off-by: Andi Kleen <ak@linux.intel.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Namhyung Kim <namhyung.kim@lge.com> Cc: Peter Zijlstra <peterz@infradead.org> Link: http://lkml.kernel.org/r/1359040242-8269-6-git-send-email-eranian@google.com [ committer note: changed to cope with fc5871ed and the hists_link perf test entry ] Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/Documentation/perf-record.txt6
-rw-r--r--tools/perf/Documentation/perf-report.txt2
-rw-r--r--tools/perf/Documentation/perf-top.txt2
-rw-r--r--tools/perf/builtin-annotate.c2
-rw-r--r--tools/perf/builtin-diff.c7
-rw-r--r--tools/perf/builtin-record.c2
-rw-r--r--tools/perf/builtin-report.c8
-rw-r--r--tools/perf/builtin-top.c5
-rw-r--r--tools/perf/perf.h1
-rw-r--r--tools/perf/tests/hists_link.c4
-rw-r--r--tools/perf/util/event.h1
-rw-r--r--tools/perf/util/evsel.c10
-rw-r--r--tools/perf/util/hist.c23
-rw-r--r--tools/perf/util/hist.h8
-rw-r--r--tools/perf/util/session.c3
-rw-r--r--tools/perf/util/sort.c45
-rw-r--r--tools/perf/util/sort.h3
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
182The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k 182The various filters must be specified as a comma separated list: --branch-filter any_ret,u,k
183Note that this feature may not be available on all processors. 183Note that this feature may not be available on all processors.
184 184
185-W::
186--weight::
187Enable weightened sampling. An additional weight is recorded per sample and can be
188displayed with the weight and local_weight sort keys. This currently works for TSX
189abort events and some memory events in precise mode on modern Intel CPUs.
190
185SEE ALSO 191SEE ALSO
186-------- 192--------
187linkperf:perf-stat[1], linkperf:perf-list[1] 193linkperf: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
233static int hists__add_entry(struct hists *self, 233static 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
158static void he_stat__add_period(struct he_stat *he_stat, u64 period) 158static 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
174static void hist_entry__decay(struct hist_entry *he) 177static 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
180static bool hists__decay_entry(struct hists *hists, struct hist_entry *he) 184static bool hists__decay_entry(struct hists *hists, struct hist_entry *he)
@@ -282,7 +286,8 @@ static u8 symbol__parent_filter(const struct symbol *parent)
282static struct hist_entry *add_hist_entry(struct hists *hists, 286static 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
372struct hist_entry *__hists__add_entry(struct hists *self, 379struct 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
397int64_t 406int64_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
74struct hist_entry *__hists__add_entry(struct hists *self, 76struct 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);
77int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right); 80int64_t hist_entry__cmp(struct hist_entry *left, struct hist_entry *right);
78int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right); 81int64_t hist_entry__collapse(struct hist_entry *left, struct hist_entry *right);
79int hist_entry__sort_snprintf(struct hist_entry *self, char *bf, size_t size, 82int 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
89void hists__output_resort(struct hists *self); 93void hists__output_resort(struct hists *self);
90void hists__output_resort_threaded(struct hists *hists); 94void 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
803static struct machine * 806static 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
467static u64 he_weight(struct hist_entry *he)
468{
469 return he->stat.nr_events ? he->stat.weight / he->stat.nr_events : 0;
470}
471
472static int64_t
473sort__local_weight_cmp(struct hist_entry *left, struct hist_entry *right)
474{
475 return he_weight(left) - he_weight(right);
476}
477
478static 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
484struct 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
491static int64_t
492sort__global_weight_cmp(struct hist_entry *left, struct hist_entry *right)
493{
494 return left->stat.weight - right->stat.weight;
495}
496
497static 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
503struct 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
467struct sort_dimension { 510struct 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,