From: Namhyung Kim <namhyung@kernel.org>
To: Arnaldo Carvalho de Melo <acme@kernel.org>,
Jiri Olsa <jolsa@kernel.org>,
Peter Zijlstra <peterz@infradead.org>
Cc: Ian Rogers <irogers@google.com>,
Adrian Hunter <adrian.hunter@intel.com>,
Ingo Molnar <mingo@kernel.org>,
LKML <linux-kernel@vger.kernel.org>,
linux-perf-users@vger.kernel.org,
Linus Torvalds <torvalds@linux-foundation.org>,
Stephane Eranian <eranian@google.com>,
Masami Hiramatsu <mhiramat@kernel.org>,
linux-toolchains@vger.kernel.org,
linux-trace-devel@vger.kernel.org
Subject: [PATCH 14/17] perf annotate: Add --data-type option
Date: Tue, 12 Dec 2023 16:13:20 -0800 [thread overview]
Message-ID: <20231213001323.718046-15-namhyung@kernel.org> (raw)
In-Reply-To: <20231213001323.718046-1-namhyung@kernel.org>
Support data type annotation with new --data-type option. It internally
uses type sort key to collect sample histogram for the type and display
every members like below.
$ perf annotate --data-type
...
Annotate type: 'struct cfs_rq' in [kernel.kallsyms] (13 samples):
============================================================================
samples offset size field
13 0 640 struct cfs_rq {
2 0 16 struct load_weight load {
2 0 8 unsigned long weight;
0 8 4 u32 inv_weight;
};
0 16 8 unsigned long runnable_weight;
0 24 4 unsigned int nr_running;
1 28 4 unsigned int h_nr_running;
...
For simplicity it prints the number of samples per field for now.
But it should be easy to show the overhead percentage instead.
The number at the outer struct is a sum of the numbers of the inner
members. For example, struct cfs_rq got total 13 samples, and 2 came
from the load (struct load_weight) and 1 from h_nr_running. Similarly,
the struct load_weight got total 2 samples and they all came from the
weight field.
I've added two new flags in the symbol_conf for this. The
annotate_data_member is to get the members of the type. This is also
needed for perf report with typeoff sort key. The annotate_data_sample
is to update sample stats for each offset and used only in annotate.
Currently it only support stdio output mode, TUI support can be added
later.
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
---
tools/perf/Documentation/perf-annotate.txt | 8 ++
tools/perf/builtin-annotate.c | 97 +++++++++++++++++++++-
tools/perf/util/annotate-data.c | 8 +-
tools/perf/util/annotate.c | 10 ++-
tools/perf/util/sort.c | 2 +
tools/perf/util/symbol_conf.h | 4 +-
6 files changed, 118 insertions(+), 11 deletions(-)
diff --git a/tools/perf/Documentation/perf-annotate.txt b/tools/perf/Documentation/perf-annotate.txt
index fe168e8165c8..0e6a49b7795c 100644
--- a/tools/perf/Documentation/perf-annotate.txt
+++ b/tools/perf/Documentation/perf-annotate.txt
@@ -155,6 +155,14 @@ include::itrace.txt[]
stdio or stdio2 (Default: 0). Note that this is about selection of
functions to display, not about lines within the function.
+--data-type[=TYPE_NAME]::
+ Display data type annotation instead of code. It infers data type of
+ samples (if they are memory accessing instructions) using DWARF debug
+ information. It can take an optional argument of data type name. In
+ that case it'd show annotation for the type only, otherwise it'd show
+ all data types it finds.
+
+
SEE ALSO
--------
linkperf:perf-record[1], linkperf:perf-report[1]
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index d880f1b039fd..8acfbbc1b9c2 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -20,6 +20,7 @@
#include "util/evlist.h"
#include "util/evsel.h"
#include "util/annotate.h"
+#include "util/annotate-data.h"
#include "util/event.h"
#include <subcmd/parse-options.h>
#include "util/parse-events.h"
@@ -55,9 +56,11 @@ struct perf_annotate {
bool skip_missing;
bool has_br_stack;
bool group_set;
+ bool data_type;
float min_percent;
const char *sym_hist_filter;
const char *cpu_list;
+ const char *target_data_type;
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
};
@@ -322,6 +325,32 @@ static int hist_entry__tty_annotate(struct hist_entry *he,
return symbol__tty_annotate2(&he->ms, evsel);
}
+static void print_annotated_data_type(struct annotated_data_type *mem_type,
+ struct annotated_member *member,
+ struct evsel *evsel, int indent)
+{
+ struct annotated_member *child;
+ struct type_hist *h = mem_type->histograms[evsel->core.idx];
+ int i, samples = 0;
+
+ for (i = 0; i < member->size; i++)
+ samples += h->addr[member->offset + i].nr_samples;
+
+ printf(" %10d %10d %10d %*s%s\t%s",
+ samples, member->offset, member->size, indent, "", member->type_name,
+ member->var_name ?: "");
+
+ if (!list_empty(&member->children))
+ printf(" {\n");
+
+ list_for_each_entry(child, &member->children, node)
+ print_annotated_data_type(mem_type, child, evsel, indent + 4);
+
+ if (!list_empty(&member->children))
+ printf("%*s}", 35 + indent, "");
+ printf(";\n");
+}
+
static void hists__find_annotations(struct hists *hists,
struct evsel *evsel,
struct perf_annotate *ann)
@@ -361,6 +390,40 @@ static void hists__find_annotations(struct hists *hists,
continue;
}
+ if (ann->data_type) {
+ struct dso *dso = map__dso(he->ms.map);
+
+ /* skip unknown type */
+ if (he->mem_type->histograms == NULL)
+ goto find_next;
+
+ if (ann->target_data_type) {
+ const char *type_name = he->mem_type->self.type_name;
+
+ /* skip 'struct ' prefix in the type name */
+ if (strncmp(ann->target_data_type, "struct ", 7) &&
+ !strncmp(type_name, "struct ", 7))
+ type_name += 7;
+
+ /* skip 'union ' prefix in the type name */
+ if (strncmp(ann->target_data_type, "union ", 6) &&
+ !strncmp(type_name, "union ", 6))
+ type_name += 6;
+
+ if (strcmp(ann->target_data_type, type_name))
+ goto find_next;
+ }
+
+ printf("Annotate type: '%s' in %s (%d samples):\n",
+ he->mem_type->self.type_name, dso->name, he->stat.nr_events);
+ printf("============================================================================\n");
+ printf(" %10s %10s %10s %s\n", "samples", "offset", "size", "field");
+
+ print_annotated_data_type(he->mem_type, &he->mem_type->self, evsel, 0);
+ printf("\n");
+ goto find_next;
+ }
+
if (use_browser == 2) {
int ret;
int (*annotate)(struct hist_entry *he,
@@ -496,6 +559,17 @@ static int parse_percent_limit(const struct option *opt, const char *str,
return 0;
}
+static int parse_data_type(const struct option *opt, const char *str, int unset)
+{
+ struct perf_annotate *ann = opt->value;
+
+ ann->data_type = !unset;
+ if (str)
+ ann->target_data_type = strdup(str);
+
+ return 0;
+}
+
static const char * const annotate_usage[] = {
"perf annotate [<options>]",
NULL
@@ -607,6 +681,9 @@ int cmd_annotate(int argc, const char **argv)
OPT_CALLBACK_OPTARG(0, "itrace", &itrace_synth_opts, NULL, "opts",
"Instruction Tracing options\n" ITRACE_HELP,
itrace_parse_synth_opts),
+ OPT_CALLBACK_OPTARG(0, "data-type", &annotate, NULL, "name",
+ "Show data type annotate for the memory accesses",
+ parse_data_type),
OPT_END()
};
@@ -661,6 +738,13 @@ int cmd_annotate(int argc, const char **argv)
}
#endif
+#ifndef HAVE_DWARF_GETLOCATIONS_SUPPORT
+ if (annotate.data_type) {
+ pr_err("Error: Data type profiling is disabled due to missing DWARF support\n");
+ return -ENOTSUP;
+ }
+#endif
+
ret = symbol__validate_sym_arguments();
if (ret)
return ret;
@@ -703,6 +787,14 @@ int cmd_annotate(int argc, const char **argv)
use_browser = 2;
#endif
+ /* FIXME: only support stdio for now */
+ if (annotate.data_type) {
+ use_browser = 0;
+ annotate_opts.annotate_src = false;
+ symbol_conf.annotate_data_member = true;
+ symbol_conf.annotate_data_sample = true;
+ }
+
setup_browser(true);
/*
@@ -710,7 +802,10 @@ int cmd_annotate(int argc, const char **argv)
* symbol, we do not care about the processes in annotate,
* set sort order to avoid repeated output.
*/
- sort_order = "dso,symbol";
+ if (annotate.data_type)
+ sort_order = "dso,type";
+ else
+ sort_order = "dso,symbol";
/*
* Set SORT_MODE__BRANCH so that annotate display IPC/Cycle
diff --git a/tools/perf/util/annotate-data.c b/tools/perf/util/annotate-data.c
index 9942a87b0664..06be6b279d6a 100644
--- a/tools/perf/util/annotate-data.c
+++ b/tools/perf/util/annotate-data.c
@@ -18,6 +18,7 @@
#include "map_symbol.h"
#include "strbuf.h"
#include "symbol.h"
+#include "symbol_conf.h"
/*
* Compare type name and size to maintain them in a tree.
@@ -157,11 +158,8 @@ static struct annotated_data_type *dso__findnew_data_type(struct dso *dso,
result->self.size = size;
INIT_LIST_HEAD(&result->self.children);
- /*
- * Fill member info unconditionally for now,
- * later perf annotate would need it.
- */
- add_member_types(result, type_die);
+ if (symbol_conf.annotate_data_member)
+ add_member_types(result, type_die);
rb_add(&result->node, &dso->data_types, data_type_less);
return result;
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index f966e8f83c5e..68424ee0215e 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -3712,10 +3712,12 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
mem_type = find_data_type(ms, ip, op_loc->reg, op_loc->offset);
- annotated_data_type__update_samples(mem_type, evsel,
- op_loc->offset,
- he->stat.nr_events,
- he->stat.period);
+ if (symbol_conf.annotate_data_sample) {
+ annotated_data_type__update_samples(mem_type, evsel,
+ op_loc->offset,
+ he->stat.nr_events,
+ he->stat.period);
+ }
he->mem_type_off = op_loc->offset;
return mem_type;
}
diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
index 0cbbd5ba8175..30254eb63709 100644
--- a/tools/perf/util/sort.c
+++ b/tools/perf/util/sort.c
@@ -3401,6 +3401,8 @@ int sort_dimension__add(struct perf_hpp_list *list, const char *tok,
list->thread = 1;
} else if (sd->entry == &sort_comm) {
list->comm = 1;
+ } else if (sd->entry == &sort_type_offset) {
+ symbol_conf.annotate_data_member = true;
}
return __sort_dimension__add(sd, list, level);
diff --git a/tools/perf/util/symbol_conf.h b/tools/perf/util/symbol_conf.h
index 6040286e07a6..c114bbceef40 100644
--- a/tools/perf/util/symbol_conf.h
+++ b/tools/perf/util/symbol_conf.h
@@ -44,7 +44,9 @@ struct symbol_conf {
buildid_mmap2,
guest_code,
lazy_load_kernel_maps,
- keep_exited_threads;
+ keep_exited_threads,
+ annotate_data_member,
+ annotate_data_sample;
const char *vmlinux_name,
*kallsyms_name,
*source_prefix,
--
2.43.0.472.g3155946c3a-goog
next prev parent reply other threads:[~2023-12-13 0:13 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-13 0:13 [PATCHSET 00/17] perf tools: Introduce data type profiling (v3) Namhyung Kim
2023-12-13 0:13 ` [PATCH 01/17] perf dwarf-aux: Factor out die_get_typename_from_type() Namhyung Kim
2023-12-13 0:13 ` [PATCH 02/17] perf dwarf-regs: Add get_dwarf_regnum() Namhyung Kim
2023-12-13 0:13 ` [PATCH 03/17] perf annotate-data: Add find_data_type() Namhyung Kim
2023-12-13 0:13 ` [PATCH 04/17] perf annotate-data: Add dso->data_types tree Namhyung Kim
2023-12-13 0:13 ` [PATCH 05/17] perf annotate: Factor out evsel__get_arch() Namhyung Kim
2023-12-13 0:13 ` [PATCH 06/17] perf annotate: Add annotate_get_insn_location() Namhyung Kim
2023-12-13 0:13 ` [PATCH 07/17] perf annotate: Implement hist_entry__get_data_type() Namhyung Kim
2023-12-13 0:13 ` [PATCH 08/17] perf report: Add 'type' sort key Namhyung Kim
2023-12-13 0:13 ` [PATCH 09/17] perf report: Support data type profiling Namhyung Kim
2023-12-13 0:13 ` [PATCH 10/17] perf annotate-data: Add member field in the data type Namhyung Kim
2023-12-13 0:13 ` [PATCH 11/17] perf annotate-data: Update sample histogram for type Namhyung Kim
2023-12-13 0:13 ` [PATCH 12/17] perf report: Add 'typeoff' sort key Namhyung Kim
2023-12-13 0:13 ` [PATCH 13/17] perf report: Add 'symoff' " Namhyung Kim
2023-12-13 0:13 ` Namhyung Kim [this message]
2023-12-13 0:13 ` [PATCH 15/17] perf annotate: Support event group display Namhyung Kim
2023-12-13 0:13 ` [PATCH 16/17] perf annotate: Add --type-stat option for debugging Namhyung Kim
2023-12-13 0:13 ` [PATCH 17/17] perf annotate: Add --insn-stat " Namhyung Kim
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231213001323.718046-15-namhyung@kernel.org \
--to=namhyung@kernel.org \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=eranian@google.com \
--cc=irogers@google.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-toolchains@vger.kernel.org \
--cc=linux-trace-devel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=mingo@kernel.org \
--cc=peterz@infradead.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).