* Updated patchkit to show weights in annotation
@ 2026-08-13 21:10 Andi Kleen
2026-08-13 21:10 ` [PATCH v2 1/4] perf tools record: Modernize -W man page Andi Kleen
` (3 more replies)
0 siblings, 4 replies; 10+ messages in thread
From: Andi Kleen @ 2026-08-13 21:10 UTC (permalink / raw)
To: namhyung; +Cc: acme, linux-perf-users
Sashiko actually found some real bugs in its v1 review, this version
has them all fixed.
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v2 1/4] perf tools record: Modernize -W man page
2026-08-13 21:10 Updated patchkit to show weights in annotation Andi Kleen
@ 2026-08-13 21:10 ` Andi Kleen
2026-08-14 1:03 ` sashiko-bot
2026-08-13 21:10 ` [PATCH v2 2/4] perf tools top: Add --weight option Andi Kleen
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Andi Kleen @ 2026-08-13 21:10 UTC (permalink / raw)
To: namhyung; +Cc: acme, linux-perf-users, Andi Kleen
Modernize the -W / --weight description in the manpage to cover more
cases that are supported now.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/Documentation/perf-record.txt | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/tools/perf/Documentation/perf-record.txt b/tools/perf/Documentation/perf-record.txt
index 178f483140ed..2c6510c5a87b 100644
--- a/tools/perf/Documentation/perf-record.txt
+++ b/tools/perf/Documentation/perf-record.txt
@@ -480,9 +480,11 @@ Note that this feature may not be available on all processors.
-W::
--weight::
-Enable weightened sampling. An additional weight is recorded per sample and can be
-displayed with the weight and local_weight sort keys. This currently works for TSX
-abort events and some memory events in precise mode on modern Intel CPUs.
+Enable weighted sampling. One or more additional weights can be recorded per sample
+and can be displayed with the weight, weight2, weight3 and local_weight sort keys.
+Possible uses for weights are memory or instruction retirement latencies.
+Support depends on the PMU and the event, as well as its configuration. Typically
+it requires use of 'p'.
--namespaces::
Record events of type PERF_RECORD_NAMESPACES. This enables 'cgroup_id' sort key.
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 2/4] perf tools top: Add --weight option
2026-08-13 21:10 Updated patchkit to show weights in annotation Andi Kleen
2026-08-13 21:10 ` [PATCH v2 1/4] perf tools record: Modernize -W man page Andi Kleen
@ 2026-08-13 21:10 ` Andi Kleen
2026-08-14 1:08 ` sashiko-bot
2026-08-13 21:10 ` [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate Andi Kleen
2026-08-13 21:10 ` [PATCH v2 4/4] perf tools: Add test for weight annotation Andi Kleen
3 siblings, 1 reply; 10+ messages in thread
From: Andi Kleen @ 2026-08-13 21:10 UTC (permalink / raw)
To: namhyung; +Cc: acme, linux-perf-users, Andi Kleen
Add a -W/--weight option to perf top to collect weights too. Useful with
follow on patches.
Assisted-by: omp:GPT-5.6-Luna
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/Documentation/perf-top.txt | 6 ++++++
tools/perf/builtin-top.c | 2 ++
2 files changed, 8 insertions(+)
diff --git a/tools/perf/Documentation/perf-top.txt b/tools/perf/Documentation/perf-top.txt
index af3e4230c72f..2da2a16bbf26 100644
--- a/tools/perf/Documentation/perf-top.txt
+++ b/tools/perf/Documentation/perf-top.txt
@@ -25,6 +25,12 @@ OPTIONS
--count=<count>::
Event period to sample.
+-W::
+--weight::
+Enable weighted sampling. One or more additional weights can be recorded per sample
+and can be displayed with the weight, weight2, weight3 and local_weight sort keys.
+Possible uses for weights are memory or instruction retirement latencies.
+
-C <cpu-list>::
--cpu=<cpu>::
Monitor only on the list of CPUs provided. Multiple CPUs can be provided as a
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index 570410599f1b..2888ac3b7b92 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -1493,6 +1493,8 @@ int cmd_top(int argc, const char **argv)
OPT_CALLBACK(0, "filter", &top.evlist, "filter",
"event filter", parse_filter),
OPT_U64('c', "count", &opts->user_interval, "event period to sample"),
+ OPT_BOOLEAN('W', "weight", &opts->sample_weight,
+ "sample by weight (on special events only)"),
OPT_STRING('p', "pid", &target->pid, "pid",
"profile events on existing process id"),
OPT_STRING('t', "tid", &target->tid, "tid",
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate
2026-08-13 21:10 Updated patchkit to show weights in annotation Andi Kleen
2026-08-13 21:10 ` [PATCH v2 1/4] perf tools record: Modernize -W man page Andi Kleen
2026-08-13 21:10 ` [PATCH v2 2/4] perf tools top: Add --weight option Andi Kleen
@ 2026-08-13 21:10 ` Andi Kleen
2026-08-14 1:28 ` sashiko-bot
2026-08-14 6:19 ` Namhyung Kim
2026-08-13 21:10 ` [PATCH v2 4/4] perf tools: Add test for weight annotation Andi Kleen
3 siblings, 2 replies; 10+ messages in thread
From: Andi Kleen @ 2026-08-13 21:10 UTC (permalink / raw)
To: namhyung; +Cc: acme, linux-perf-users, Andi Kleen
Add support for showing all the three possible per IP weights in
annotate. The weights are shown by defaults if any are non zero. This
is useful, especially with the new insn lat statistics, but also
for all the existing weights.
Add a hotkey to the interactive browser to turn them off (w), as well
as a perf annotate command line option.
The weights are stored unconditionally in the sym_hist_entry, which
will increase memory consumption somewhat.
Assisted-by: omp:GPT-5.6-Luna
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/Documentation/perf-annotate.txt | 3 +
tools/perf/builtin-annotate.c | 3 +
tools/perf/builtin-report.c | 1 +
tools/perf/ui/browsers/annotate.c | 17 ++-
tools/perf/util/annotate.c | 117 ++++++++++++++++++---
tools/perf/util/annotate.h | 32 +++++-
tools/perf/util/symbol.c | 1 +
tools/perf/util/symbol_conf.h | 17 ++-
8 files changed, 170 insertions(+), 21 deletions(-)
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index a688738809c4..50c6ea680d0d 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -79,6 +79,9 @@ include::itrace.txt[]
--stdio:: Use the stdio interface.
+--no-weights:: Hide weight columns in annotation output. By default, weight columns
+ are shown when samples contain non-zero weights.
+
--stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
--stdio-color=<mode>::
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 69cb72b2082a..c6c481145e45 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -259,6 +259,7 @@ static int add_sample(struct perf_sample *sample,
return 0;
}
+
/*
* XXX filtered samples can still have branch entries pointing into our
* symbol and are missed.
@@ -719,6 +720,8 @@ int cmd_annotate(int argc, const char **argv)
OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
#endif
OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
+ OPT_BOOLEAN(0, "no-weights", &symbol_conf.hide_weight,
+ "Hide weight columns in annotation"),
OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
"don't load vmlinux even if found"),
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c
index 60d1f166629e..921aa03093f3 100644
--- a/tools/perf/builtin-report.c
+++ b/tools/perf/builtin-report.c
@@ -329,6 +329,7 @@ static int process_sample_event(const struct perf_tool *tool,
&rep->total_cycles);
}
+
rep->total_samples++;
if (al.parallelism == 1)
rep->singlethreaded_samples++;
diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
index e47a46775089..d6126a7d51e4 100644
--- a/tools/perf/ui/browsers/annotate.c
+++ b/tools/perf/ui/browsers/annotate.c
@@ -189,7 +189,7 @@ static void annotate_browser__draw_current_jump(struct ui_browser *browser)
struct map_symbol *ms = ab->b.priv;
struct symbol *sym = ms->sym;
struct annotation *notes = symbol__annotation(sym);
- u8 pcnt_width = annotation__pcnt_width(notes);
+ u8 pcnt_width = annotation__pcnt_width(notes, ab->evsel);
u8 cntr_width = annotation__br_cntr_width();
int width;
int diff = 0;
@@ -255,7 +255,8 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)
{
struct annotation *notes = browser__annotation(browser);
int ret = ui_browser__list_head_refresh(browser);
- int pcnt_width = annotation__pcnt_width(notes);
+ int pcnt_width = annotation__pcnt_width(notes,
+ container_of(browser, struct annotate_browser, b)->evsel);
if (annotate_opts.jump_arrows)
annotate_browser__draw_current_jump(browser);
@@ -972,6 +973,7 @@ static int annotate_browser__run(struct annotate_browser *browser,
"O Bump offset level (jump targets -> +call -> all -> cycle thru)\n"
"s Toggle source code view\n"
"t Circulate percent, total period, samples view\n"
+ "w Toggle weight columns\n"
"c Show min/max cycle\n"
"/ Search string\n"
"k Toggle line numbers\n"
@@ -1091,6 +1093,15 @@ static int annotate_browser__run(struct annotate_browser *browser,
symbol_conf.show_total_period = true;
annotation__update_column_widths(notes);
continue;
+ case 'w':
+ symbol_conf.hide_weight = !symbol_conf.hide_weight;
+ symbol_conf.weight_mask_user = true;
+ symbol_conf.weight_mask = symbol_conf.hide_weight ?
+ 0 : sym_hist__weight_mask(annotation__histogram(notes, evsel));
+ browser->b.width = notes->src->widths.max_line_len +
+ annotation__pcnt_width(notes, evsel);
+ ui_browser__refresh_dimensions(&browser->b);
+ continue;
case 'c':
if (annotate_opts.show_minmax_cycle)
annotate_opts.show_minmax_cycle = false;
@@ -1228,7 +1239,7 @@ int __hist_entry__tui_annotate(struct hist_entry *he, struct map_symbol *ms,
browser.b.width = notes->src->widths.max_line_len;
browser.b.nr_entries = notes->src->nr_entries;
browser.b.entries = ¬es->src->source;
- browser.b.width += 18; /* Percentage */
+ browser.b.width += annotation__pcnt_width(notes, evsel);
if (annotate_opts.hide_src_code)
ui_browser__init_asm_mode(&browser.b);
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index df70e95a8470..b636f54675a1 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -222,6 +222,7 @@ static int __symbol__inc_addr_samples(struct map_symbol *ms,
u64 offset;
struct sym_hist *h;
struct sym_hist_entry *entry;
+ u64 weight = sample->weight ?: sample->ins_lat ?: sample->weight3;
pr_debug3("%s: addr=%#" PRIx64 "\n", __func__, map__unmap_ip(ms->map, addr));
@@ -256,10 +257,28 @@ static int __symbol__inc_addr_samples(struct map_symbol *ms,
entry->nr_samples++;
entry->period += sample->period;
+ if (sample->evsel->core.attr.sample_type & PERF_SAMPLE_WEIGHT_TYPE) {
+ entry->weight_sum[WEIGHT_WEIGHT] += sample->weight;
+ entry->weight_num[WEIGHT_WEIGHT]++;
+ if (sample->weight)
+ sym_hist__set_weight_mask(h, BIT(WEIGHT_WEIGHT));
+ }
+ if (sample->evsel->core.attr.sample_type & PERF_SAMPLE_WEIGHT_STRUCT) {
+ entry->weight_sum[WEIGHT_INSNLAT] += sample->ins_lat;
+ entry->weight_num[WEIGHT_INSNLAT]++;
+ entry->weight_sum[WEIGHT_WEIGHT3] += sample->weight3;
+ entry->weight_num[WEIGHT_WEIGHT3]++;
+ if (sample->ins_lat)
+ sym_hist__set_weight_mask(h, BIT(WEIGHT_INSNLAT));
+ if (sample->weight3)
+ sym_hist__set_weight_mask(h, BIT(WEIGHT_WEIGHT3));
+ }
+
pr_debug3("%#" PRIx64 " %s: period++ [addr: %#" PRIx64 ", %#" PRIx64
- ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64 "\n",
+ ", evidx=%d] => nr_samples: %" PRIu64 ", period: %" PRIu64
+ " weight %" PRIu64 "\n",
sym->start, sym->name, addr, addr - sym->start, evsel->core.idx,
- entry->nr_samples, entry->period);
+ entry->nr_samples, entry->period, weight);
return 0;
}
@@ -778,6 +797,41 @@ static bool needs_type_info(struct annotated_data_type *data_type)
return (data_type != &stackop_type) && (data_type != &canary_type);
}
+static const char *annotation__weight_mode_str(enum symbol__weight_mode mode)
+{
+ switch (mode) {
+ case WEIGHT_NONE:
+ return "";
+ case WEIGHT_WEIGHT:
+ return "Weight";
+ case WEIGHT_INSNLAT:
+ return "InsnLat";
+ case WEIGHT_WEIGHT3:
+ return "Weight3";
+ default:
+ return "";
+ }
+}
+
+static void annotation__column_title(char *buf, size_t size,
+ struct annotation *notes,
+ const struct evsel *evsel)
+{
+ const char *base = symbol_conf.show_total_period ? "Period" :
+ symbol_conf.show_nr_samples ? "Samples" : "Percent";
+ int weight;
+ u8 weight_mask = annotation__weight_mask(notes, evsel);
+
+ scnprintf(buf, size, "%s", base);
+ for_each_weight(weight) {
+ if (weight_mask & BIT(weight))
+ scnprintf(buf + strlen(buf),
+ size - strlen(buf),
+ " %s",
+ annotation__weight_mode_str(weight));
+ }
+}
+
static int
annotation_line__print(struct annotation_line *al, struct annotation_print_data *apd,
struct annotation_options *opts, int printed,
@@ -833,6 +887,8 @@ annotation_line__print(struct annotation_line *al, struct annotation_print_data
for (i = 0; i < nr_percent; i++) {
struct annotation_data *data = &al->data[i];
double percent;
+ int weight;
+ u8 weight_mask = annotation__weight_mask(notes, apd->evsel);
percent = annotation_data__percent(data, percent_type);
color = get_percent_color(percent);
@@ -845,6 +901,13 @@ annotation_line__print(struct annotation_line *al, struct annotation_print_data
data->he.nr_samples);
else
color_fprintf(stdout, color, " %7.2f", percent);
+ for_each_weight(weight) {
+ if (weight_mask & BIT(weight))
+ color_fprintf(stdout, color, " %7" PRIu64,
+ data->he.weight_num[weight] ?
+ data->he.weight_sum[weight] / data->he.weight_num[weight]
+ : 0);
+ }
}
printf(" : ");
@@ -891,7 +954,7 @@ annotation_line__print(struct annotation_line *al, struct annotation_print_data
} else if (max_lines && printed >= max_lines)
return 1;
else {
- int width = annotation__pcnt_width(notes);
+ int width = annotation__pcnt_width(notes, apd->evsel);
if (queue)
return -1;
@@ -915,6 +978,9 @@ static void calc_percent(struct annotation *notes,
struct sym_hist *sym_hist = annotation__histogram(notes, evsel);
unsigned int hits = 0;
u64 period = 0;
+ int i;
+ u64 weight_sum[WEIGHT_WEIGHT3 + 1] = { 0 };
+ u64 weight_num[WEIGHT_WEIGHT3 + 1] = { 0 };
while (offset < end) {
struct sym_hist_entry *entry;
@@ -923,6 +989,10 @@ static void calc_percent(struct annotation *notes,
if (entry) {
hits += entry->nr_samples;
period += entry->period;
+ for_each_weight(i) {
+ weight_sum[i] += entry->weight_sum[i];
+ weight_num[i] += entry->weight_num[i];
+ }
}
++offset;
}
@@ -930,6 +1000,10 @@ static void calc_percent(struct annotation *notes,
if (sym_hist->nr_samples) {
data->he.period = period;
data->he.nr_samples = hits;
+ for_each_weight(i) {
+ data->he.weight_sum[i] = weight_sum[i];
+ data->he.weight_num[i] = weight_num[i];
+ }
data->percent[PERCENT_HITS_LOCAL] = 100.0 * hits / sym_hist->nr_samples;
}
@@ -1252,9 +1326,10 @@ int hist_entry__annotate_printf(struct hist_entry *he, struct evsel *evsel)
int printed = 2, queue_len = 0;
int more = 0;
bool context = opts->context;
- int width = annotation__pcnt_width(notes);
int graph_dotted_len;
+ char title[64];
char buf[512];
+ int width = annotation__pcnt_width(notes, evsel);
filename = strdup(dso__long_name(dso));
if (!filename)
@@ -1275,10 +1350,10 @@ int hist_entry__annotate_printf(struct hist_entry *he, struct evsel *evsel)
return ENOTSUP;
}
- graph_dotted_len = printf(" %-*.*s| Source code & Disassembly of %s for %s (%" PRIu64 " samples, "
+ annotation__column_title(title, sizeof(title), notes, evsel);
+ graph_dotted_len = printf(" %-*.*s|\tSource code & Disassembly of %s for %s (%" PRIu64 " samples, "
"percent: %s)\n",
- width, width, symbol_conf.show_total_period ? "Period" :
- symbol_conf.show_nr_samples ? "Samples" : "Percent",
+ width, width, title,
d_filename, evsel_name, h->nr_samples,
percent_type_str(opts->percent_type));
@@ -1448,7 +1523,8 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
return err;
}
-void symbol__annotate_zero_histogram(struct symbol *sym, struct evsel *evsel)
+void symbol__annotate_zero_histogram(struct symbol *sym,
+ struct evsel *evsel)
{
struct annotation *notes = symbol__annotation(sym);
struct sym_hist *h = annotation__histogram(notes, evsel);
@@ -2029,7 +2105,8 @@ static int disasm_line__snprint_type_info(struct disasm_line *dl,
return printed;
}
-void annotation_line__write(struct annotation_line *al, struct annotation *notes,
+void annotation_line__write(struct annotation_line *al,
+ struct annotation *notes,
const struct annotation_write_ops *wops,
struct annotation_print_data *apd)
{
@@ -2037,15 +2114,16 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
bool change_color = wops->change_color;
double percent_max = annotation_line__max_percent(al, annotate_opts.percent_type);
int width = wops->width;
- int pcnt_width = annotation__pcnt_width(notes);
+ int pcnt_width = annotation__pcnt_width(notes, apd->evsel);
+ u8 weight_mask = annotation__weight_mask(notes, apd->evsel);
int cycles_width = annotation__cycles_width(notes);
bool show_title = false;
char bf[256];
int printed;
void *obj = wops->obj;
- int (*obj__set_color)(void *obj, int color) = wops->set_color;
+ int (*obj__set_color)(void *obj, int color) = wops->set_color;
void (*obj__set_percent_color)(void *obj, double percent, bool current) = wops->set_percent_color;
- int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current) = wops->set_jumps_percent_color;
+ int (*obj__set_jumps_percent_color)(void *obj, int nr, bool current) = wops->set_jumps_percent_color;
void (*obj__printf)(void *obj, const char *fmt, ...) = wops->printf;
void (*obj__write_graph)(void *obj, int graph) = wops->write_graph;
@@ -2062,6 +2140,7 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
for (i = 0; i < al->data_nr; i++) {
double percent;
+ int weight;
percent = annotation_data__percent(&al->data[i],
annotate_opts.percent_type);
@@ -2075,6 +2154,14 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
} else {
obj__printf(obj, "%7.2f ", percent);
}
+
+ for_each_weight(weight) {
+ if (weight_mask & BIT(weight))
+ obj__printf(obj, "%7" PRIu64 " ",
+ al->data[i].he.weight_num[weight] ?
+ al->data[i].he.weight_sum[weight] / al->data[i].he.weight_num[weight] :
+ 0);
+ }
}
} else {
obj__set_percent_color(obj, 0, current_entry);
@@ -2082,9 +2169,9 @@ void annotation_line__write(struct annotation_line *al, struct annotation *notes
if (!show_title)
obj__printf(obj, "%-*s", pcnt_width, " ");
else {
- obj__printf(obj, "%-*s", pcnt_width,
- symbol_conf.show_total_period ? "Period" :
- symbol_conf.show_nr_samples ? "Samples" : "Percent");
+ char buf[64];
+ annotation__column_title(buf, sizeof(buf), notes, apd->evsel);
+ obj__printf(obj, "%-*s", pcnt_width, buf);
}
}
width -= pcnt_width;
diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
index fa08d09b80f7..63bce7a920f3 100644
--- a/tools/perf/util/annotate.h
+++ b/tools/perf/util/annotate.h
@@ -6,6 +6,7 @@
#include <stdint.h>
#include <stdio.h>
#include <linux/types.h>
+#include <linux/bitops.h>
#include <linux/list.h>
#include <linux/rbtree.h>
#include <asm/bug.h>
@@ -86,6 +87,8 @@ struct annotation;
struct sym_hist_entry {
u64 nr_samples;
u64 period;
+ u64 weight_sum[WEIGHT_WEIGHT3 + 1];
+ u64 weight_num[WEIGHT_WEIGHT3 + 1];
};
enum {
@@ -231,8 +234,20 @@ void symbol__calc_percent(struct symbol *sym, struct evsel *evsel);
struct sym_hist {
u64 nr_samples;
u64 period;
+ u8 weight_mask;
};
+/* Can be set asynchronously by top. */
+static inline u8 sym_hist__weight_mask(const struct sym_hist *hist)
+{
+ return __atomic_load_n(&hist->weight_mask, __ATOMIC_RELAXED);
+}
+
+static inline void sym_hist__set_weight_mask(struct sym_hist *hist, u8 mask)
+{
+ __atomic_fetch_or(&hist->weight_mask, mask, __ATOMIC_RELAXED);
+}
+
/**
* struct cyc_hist - (CPU) cycle histogram for a basic block
*
@@ -376,9 +391,22 @@ static inline int annotation__cycles_width(struct annotation *notes)
return notes->branch ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
}
-static inline int annotation__pcnt_width(struct annotation *notes)
+static inline u8 annotation__weight_mask(struct annotation *notes,
+ const struct evsel *evsel)
+{
+ if (symbol_conf.weight_mask_user)
+ return symbol_conf.weight_mask;
+ if (symbol_conf.hide_weight)
+ return 0;
+ return sym_hist__weight_mask(¬es->src->histograms[evsel->core.idx]);
+}
+
+static inline int annotation__pcnt_width(struct annotation *notes,
+ const struct evsel *evsel)
{
- return (symbol_conf.show_total_period ? 12 : 8) * notes->src->nr_events;
+ int extra = hweight8(annotation__weight_mask(notes, evsel)) * 8;
+ return ((symbol_conf.show_total_period ? 12 : 8) + extra) *
+ notes->src->nr_events;
}
static inline bool annotation_line__filter(struct annotation_line *al)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 94f9c8faedda..92dcce617de2 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2763,3 +2763,4 @@ char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
return java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
}
+
diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
index 0dee5aa6a534..8b074121b680 100644
--- a/tools/perf/util/symbol_conf.h
+++ b/tools/perf/util/symbol_conf.h
@@ -27,6 +27,16 @@ enum a2l_style {
};
#define MAX_A2L_STYLE (A2L_STYLE_CMD + 1)
+enum symbol__weight_mode {
+ WEIGHT_NONE = 0,
+ WEIGHT_WEIGHT,
+ WEIGHT_INSNLAT,
+ WEIGHT_WEIGHT3,
+};
+
+#define for_each_weight(_weight) \
+ for ((_weight) = WEIGHT_WEIGHT; (_weight) <= WEIGHT_WEIGHT3; (_weight)++)
+
struct symbol_conf {
bool nanosecs;
unsigned short priv_size;
@@ -69,7 +79,10 @@ struct symbol_conf {
annotate_data_sample,
skip_empty,
enable_latency,
- prefer_latency;
+ prefer_latency,
+ hide_weight,
+ weight_mask_user;
+ u8 weight_mask;
const char *vmlinux_name,
*kallsyms_name,
*source_prefix,
@@ -114,4 +127,6 @@ struct symbol_conf {
extern struct symbol_conf symbol_conf;
+struct perf_sample;
+
#endif // __PERF_SYMBOL_CONF
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH v2 4/4] perf tools: Add test for weight annotation
2026-08-13 21:10 Updated patchkit to show weights in annotation Andi Kleen
` (2 preceding siblings ...)
2026-08-13 21:10 ` [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate Andi Kleen
@ 2026-08-13 21:10 ` Andi Kleen
2026-08-14 1:38 ` sashiko-bot
3 siblings, 1 reply; 10+ messages in thread
From: Andi Kleen @ 2026-08-13 21:10 UTC (permalink / raw)
To: namhyung; +Cc: acme, linux-perf-users, Andi Kleen
Add a test case to check if --stdio weight annotation works
Assisted-by: omp:GPT-5.6-Luna
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/perf/tests/shell/annotate_weight.sh | 63 +++++++++++++++++++++++
1 file changed, 63 insertions(+)
create mode 100755 tools/perf/tests/shell/annotate_weight.sh
diff --git a/tools/perf/tests/shell/annotate_weight.sh b/tools/perf/tests/shell/annotate_weight.sh
new file mode 100755
index 000000000000..6b8c105c048b
--- /dev/null
+++ b/tools/perf/tests/shell/annotate_weight.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+# perf annotate weight regression test
+# SPDX-License-Identifier: GPL-2.0
+
+set -e
+
+shelldir=$(dirname "$0")
+# shellcheck source=tools/perf/tests/shell/lib/perf_has_symbol.sh
+. "${shelldir}"/lib/perf_has_symbol.sh
+
+testsym="test_loop"
+skip_test_missing_symbol "${testsym}"
+
+perfdata=$(mktemp /tmp/__perf_test.annotate_weight.XXXXX)
+record_log=$(mktemp /tmp/__perf_test.annotate_weight.XXXXX.log)
+report_out=$(mktemp /tmp/__perf_test.annotate_weight.XXXXX.report)
+annotate_out=$(mktemp /tmp/__perf_test.annotate_weight.XXXXX.annotate)
+
+cleanup() {
+ rm -f "${perfdata}" "${record_log}" "${report_out}" "${annotate_out}"
+ trap - EXIT TERM INT
+}
+
+trap 'cleanup; exit 1' TERM INT
+trap cleanup EXIT
+
+# mem-loads:pu requests a precise user PEBS event whose sample weight should
+# be populated by -W. Unsupported PEBS/weight PMUs are skipped below.
+if ! perf record -W -e mem-loads:pu -o "${perfdata}" -- perf test -w thloop \
+ > /dev/null 2> "${record_log}"; then
+ echo "[SKIP] precise PEBS weight sampling is unavailable"
+ exit 2
+fi
+
+# Confirm the PMU actually produced nonzero weights. A successful record alone
+# is insufficient: some PMUs accept the event but provide no weight payload.
+if ! perf report --stdio -i "${perfdata}" --fields=weight1,weight2,weight3,symbol --percent-limit 0 \
+ > "${report_out}" 2> "${record_log}"; then
+ echo "[SKIP] weighted samples cannot be decoded"
+ exit 2
+fi
+
+if ! awk '$1 ~ /^[0-9]/ && ($1 + 0) > 0 { found = 1 } END { exit !found }' \
+ "${report_out}"; then
+ echo "[SKIP] PEBS weight sampling produced no nonzero weights"
+ exit 2
+fi
+
+perf annotate --stdio -i "${perfdata}" --symbol "${testsym}" \
+ > "${annotate_out}" 2> "${record_log}"
+
+grep -q 'Percent Weight' "${annotate_out}"
+
+# The second numeric column is the rendered average weight. This assertion
+# fails on the original regression because calc_percent() left it at zero.
+if ! awk '$1 ~ /^[0-9]/ && $2 ~ /^[0-9]/ && ($2 + 0) > 0 { found = 1 } END { exit !found }' \
+ "${annotate_out}"; then
+ echo "Annotation output contained no nonzero weight"
+ cat "${annotate_out}"
+ exit 1
+fi
+
+echo "PEBS annotation weights: PASS"
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v2 1/4] perf tools record: Modernize -W man page
2026-08-13 21:10 ` [PATCH v2 1/4] perf tools record: Modernize -W man page Andi Kleen
@ 2026-08-14 1:03 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-14 1:03 UTC (permalink / raw)
To: Andi Kleen; +Cc: linux-perf-users
> Modernize the -W / --weight description in the manpage to cover more
> cases that are supported now.
>
> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260813211109.240689-1-ak@linux.intel.com?part=1
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 2/4] perf tools top: Add --weight option
2026-08-13 21:10 ` [PATCH v2 2/4] perf tools top: Add --weight option Andi Kleen
@ 2026-08-14 1:08 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-14 1:08 UTC (permalink / raw)
To: Andi Kleen; +Cc: linux-perf-users
> Add a -W/--weight option to perf top to collect weights too. Useful with
> follow on patches.
>
> Assisted-by: omp:GPT-5.6-Luna
> Signed-off-by: Andi Kleen <ak@linux.intel.com>
Sashiko has reviewed this patch and found no issues. It looks great!
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260813211109.240689-1-ak@linux.intel.com?part=2
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate
2026-08-13 21:10 ` [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate Andi Kleen
@ 2026-08-14 1:28 ` sashiko-bot
2026-08-14 6:19 ` Namhyung Kim
1 sibling, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-14 1:28 UTC (permalink / raw)
To: Andi Kleen; +Cc: linux-perf-users
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
New issues:
- [Medium] Toggling the 'w' hotkey caches the current event's weight mask globally, corrupting weight column display for all subsequent symbols and events.
Pre-existing issues:
- [High] This problem wasn't introduced by this patch, but there is an out-of-bounds heap memory write in `symbol__annotate_zero_histogram()` when zeroing an event's histogram.
--
--- Patch [3]: [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate ---
commit 89fdbcaac6998b08ac6d1c7549a509183b024849
Author: Andi Kleen <ak@linux.intel.com>
perf tools: Add support for displaying weights in annotate
Add support for showing all the three possible per IP weights in
annotate. The weights are shown by defaults if any are non zero. This
is useful, especially with the new insn lat statistics, but also
for all the existing weights.
> diff --git a/tools/perf/ui/browsers/annotate.c b/tools/perf/ui/browsers/annotate.c
> index e47a467750890..d6126a7d51e4a 100644
> --- a/tools/perf/ui/browsers/annotate.c
> +++ b/tools/perf/ui/browsers/annotate.c
[ ... ]
> @@ -1091,6 +1093,15 @@ static int annotate_browser__run(struct annotate_browser *browser,
> symbol_conf.show_total_period = true;
> annotation__update_column_widths(notes);
> continue;
> + case 'w':
> + symbol_conf.hide_weight = !symbol_conf.hide_weight;
> + symbol_conf.weight_mask_user = true;
> + symbol_conf.weight_mask = symbol_conf.hide_weight ?
> + 0 : sym_hist__weight_mask(annotation__histogram(notes, evsel));
> + browser->b.width = notes->src->widths.max_line_len +
> + annotation__pcnt_width(notes, evsel);
> + ui_browser__refresh_dimensions(&browser->b);
> + continue;
[ ... ]
> diff --git a/tools/perf/util/annotate.h b/tools/perf/util/annotate.h
> index fa08d09b80f76..63bce7a920f32 100644
> --- a/tools/perf/util/annotate.h
> +++ b/tools/perf/util/annotate.h
[ ... ]
> @@ -376,9 +391,22 @@ static inline int annotation__cycles_width(struct annotation *notes)
> return notes->branch ? ANNOTATION__IPC_WIDTH + ANNOTATION__CYCLES_WIDTH : 0;
> }
>
> -static inline int annotation__pcnt_width(struct annotation *notes)
> +static inline u8 annotation__weight_mask(struct annotation *notes,
> + const struct evsel *evsel)
> +{
> + if (symbol_conf.weight_mask_user)
> + return symbol_conf.weight_mask;
[Severity: Medium]
Will this globally cache the current event's dynamically generated weight mask?
In annotate_browser__run(), pressing 'w' sets symbol_conf.weight_mask_user to
true and saves the mask. Returning that cached mask here seems to force all
subsequently viewed symbols and events to use this exact column layout.
If a different event has different weight types, or if in perf top new weight
types arrive after 'w' is pressed, would the UI incorrectly hide valid weight
columns or display empty zero-filled columns for missing weights?
> + if (symbol_conf.hide_weight)
> + return 0;
> + return sym_hist__weight_mask(¬es->src->histograms[evsel->core.idx]);
> +}
[ ... ]
> diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
> index df70e95a84704..b636f54675a1e 100644
> --- a/tools/perf/util/annotate.c
> +++ b/tools/perf/util/annotate.c
[ ... ]
> @@ -1448,7 +1523,8 @@ int map_symbol__annotation_dump(struct map_symbol *ms, struct evsel *evsel,
> return err;
> }
>
> -void symbol__annotate_zero_histogram(struct symbol *sym, struct evsel *evsel)
> +void symbol__annotate_zero_histogram(struct symbol *sym,
> + struct evsel *evsel)
> {
> struct annotation *notes = symbol__annotation(sym);
> struct sym_hist *h = annotation__histogram(notes, evsel);
[Severity: High]
This is a pre-existing issue, but does the memset in this function cause an
out-of-bounds heap memory write?
When profiling multiple events (e.g. perf top -e cycles,instructions) and
zeroing the histogram (e.g. pressing 'z'), this gets called for top->sym_evsel:
void symbol__annotate_zero_histogram(...)
{
...
struct sym_hist *h = annotation__histogram(notes, evsel);
memset(h, 0, sizeof(*notes->src->histograms) * notes->src->nr_histograms);
}
The pointer h is offset to the specific event's index, but the memset zeroes
an area equal to the size of the entire histograms array. Could this write
past the end of the heap allocation?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260813211109.240689-1-ak@linux.intel.com?part=3
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 4/4] perf tools: Add test for weight annotation
2026-08-13 21:10 ` [PATCH v2 4/4] perf tools: Add test for weight annotation Andi Kleen
@ 2026-08-14 1:38 ` sashiko-bot
0 siblings, 0 replies; 10+ messages in thread
From: sashiko-bot @ 2026-08-14 1:38 UTC (permalink / raw)
To: Andi Kleen; +Cc: linux-perf-users
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The pre-condition check for non-zero weights in `perf report` output is not restricted to the target symbol `test_loop`, causing flaky test failures instead of graceful skips on CPUs with fast L1 caches.
- [Medium] The `grep -q 'Percent Weight'` command silently aborts the script on failure due to `set -e`, suppressing intended diagnostic output.
--
--- Patch [4]: [PATCH v2 4/4] perf tools: Add test for weight annotation ---
commit 4fef6c496fea22a20514f5de2e321ad5a4c0bb3e
Author: Andi Kleen <ak@linux.intel.com>
perf tools: Add test for weight annotation
This commit adds a test case to check if the --stdio weight annotation works
correctly in perf tools.
> diff --git a/tools/perf/tests/shell/annotate_weight.sh b/tools/perf/tests/shell/annotate_weight.sh
> --- /dev/null
> +++ b/tools/perf/tests/shell/annotate_weight.sh
[ ... ]
> +if ! awk '$1 ~ /^[0-9]/ && ($1 + 0) > 0 { found = 1 } END { exit !found }' \
> + "${report_out}"; then
> + echo "[SKIP] PEBS weight sampling produced no nonzero weights"
> + exit 2
> +fi
[Severity: Medium]
Will this global check cause flaky test failures on CPUs with fast L1 caches?
The awk check validates that any symbol produced non-zero weights. Since the
thloop workload spins on a volatile variable, it heavily hits the L1 cache.
On fast CPUs, these L1 hits might not trigger the PEBS mem-loads event,
meaning test_loop might produce zero samples.
However, thread initialization code can still cause cache misses and produce
samples with non-zero weights, which would pass this check. The script then
runs perf annotate for test_loop, finds zero weight, and fails the test
(exit 1) instead of properly skipping it (exit 2).
Should this condition be restricted to the target symbol test_loop before
proceeding to annotate it?
> +
> +perf annotate --stdio -i "${perfdata}" --symbol "${testsym}" \
> + > "${annotate_out}" 2> "${record_log}"
> +
> +grep -q 'Percent Weight' "${annotate_out}"
[Severity: Medium]
Because set -e is enabled at the top of the script, will this grep command
silently abort the script if the expected header is missing?
If grep returns an exit code of 1 (e.g., if the symbol had no samples or
annotation failed), the script will immediately exit and run the cleanup trap,
deleting the temporary files.
This bypasses the subsequent awk check which is explicitly designed to output
the diagnostic message "Annotation output contained no nonzero weight" and
print the file for debugging.
Could this be handled in a way that preserves the diagnostic output when it
fails?
> +
> +# The second numeric column is the rendered average weight. This assertion
> +# fails on the original regression because calc_percent() left it at zero.
> +if ! awk '$1 ~ /^[0-9]/ && $2 ~ /^[0-9]/ && ($2 + 0) > 0 { found = 1 } END { exit !found }' \
> + "${annotate_out}"; then
> + echo "Annotation output contained no nonzero weight"
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260813211109.240689-1-ak@linux.intel.com?part=4
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate
2026-08-13 21:10 ` [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate Andi Kleen
2026-08-14 1:28 ` sashiko-bot
@ 2026-08-14 6:19 ` Namhyung Kim
1 sibling, 0 replies; 10+ messages in thread
From: Namhyung Kim @ 2026-08-14 6:19 UTC (permalink / raw)
To: Andi Kleen; +Cc: acme, linux-perf-users
Hi Andi,
On Thu, Aug 13, 2026 at 02:10:09PM -0700, Andi Kleen wrote:
> Add support for showing all the three possible per IP weights in
> annotate. The weights are shown by defaults if any are non zero. This
> is useful, especially with the new insn lat statistics, but also
> for all the existing weights.
>
> Add a hotkey to the interactive browser to turn them off (w), as well
> as a perf annotate command line option.
>
> The weights are stored unconditionally in the sym_hist_entry, which
> will increase memory consumption somewhat.
>
> Assisted-by: omp:GPT-5.6-Luna
> Signed-off-by: Andi Kleen <ak@linux.intel.com>
> ---
> tools/perf/Documentation/perf-annotate.txt | 3 +
> tools/perf/builtin-annotate.c | 3 +
> tools/perf/builtin-report.c | 1 +
> tools/perf/ui/browsers/annotate.c | 17 ++-
> tools/perf/util/annotate.c | 117 ++++++++++++++++++---
> tools/perf/util/annotate.h | 32 +++++-
> tools/perf/util/symbol.c | 1 +
> tools/perf/util/symbol_conf.h | 17 ++-
> 8 files changed, 170 insertions(+), 21 deletions(-)
>
> diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
> index a688738809c4..50c6ea680d0d 100644
> --- a/tools/perf/Documentation/perf-annotate.txt
> +++ b/tools/perf/Documentation/perf-annotate.txt
> @@ -79,6 +79,9 @@ include::itrace.txt[]
>
> --stdio:: Use the stdio interface.
>
> +--no-weights:: Hide weight columns in annotation output. By default, weight columns
> + are shown when samples contain non-zero weights.
> +
> --stdio2:: Use the stdio2 interface, non-interactive, uses the TUI formatting.
>
> --stdio-color=<mode>::
> diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
> index 69cb72b2082a..c6c481145e45 100644
> --- a/tools/perf/builtin-annotate.c
> +++ b/tools/perf/builtin-annotate.c
> @@ -259,6 +259,7 @@ static int add_sample(struct perf_sample *sample,
> return 0;
> }
>
> +
> /*
> * XXX filtered samples can still have branch entries pointing into our
> * symbol and are missed.
> @@ -719,6 +720,8 @@ int cmd_annotate(int argc, const char **argv)
> OPT_BOOLEAN(0, "tui", &annotate.use_tui, "Use the TUI interface"),
> #endif
> OPT_BOOLEAN(0, "stdio", &annotate.use_stdio, "Use the stdio interface"),
> + OPT_BOOLEAN(0, "no-weights", &symbol_conf.hide_weight,
> + "Hide weight columns in annotation"),
Can it be just "weights"? Then we would get --no-weights for free. :)
Of course, the help message needs to say differently.
Thanks,
Namhyung
> OPT_BOOLEAN(0, "stdio2", &annotate.use_stdio2, "Use the stdio interface"),
> OPT_BOOLEAN(0, "ignore-vmlinux", &symbol_conf.ignore_vmlinux,
> "don't load vmlinux even if found"),
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-08-14 6:19 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-13 21:10 Updated patchkit to show weights in annotation Andi Kleen
2026-08-13 21:10 ` [PATCH v2 1/4] perf tools record: Modernize -W man page Andi Kleen
2026-08-14 1:03 ` sashiko-bot
2026-08-13 21:10 ` [PATCH v2 2/4] perf tools top: Add --weight option Andi Kleen
2026-08-14 1:08 ` sashiko-bot
2026-08-13 21:10 ` [PATCH v2 3/4] perf tools: Add support for displaying weights in annotate Andi Kleen
2026-08-14 1:28 ` sashiko-bot
2026-08-14 6:19 ` Namhyung Kim
2026-08-13 21:10 ` [PATCH v2 4/4] perf tools: Add test for weight annotation Andi Kleen
2026-08-14 1:38 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.