Commit 2f2c41bd authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

perf report: Add 'type' sort key

The 'type' sort key is to aggregate hist entries by data type they
access.  Add mem_type field to hist_entry struct to save the type.  If
hist_entry__get_data_type() returns NULL, it'd use the 'unknown_type'
instance.

Committer testing:

Before:

  # perf mem record  sleep 2s
  [ perf record: Woken up 1 times to write data ]
  [ perf record: Captured and wrote 0.037 MB perf.data (4 samples) ]
  root@number:/home/acme/Downloads# perf report --stdio -s type
  Error:
  Unknown --sort key: `type'
   Usage: perf report [<options>]

      -s, --sort <key[,key2...]>
                            sort by key(s): overhead overhead_sys overhead_us overhead_guest_sys
                            overhead_guest_us overhead_children sample period
                            pid comm dso symbol parent cpu socket srcline srcfile
                            local_weight weight transaction trace symbol_size
                            dso_size cgroup cgroup_id ipc_null time code_page_size
                            local_ins_lat ins_lat local_p_stage_cyc p_stage_cyc
                            addr local_retire_lat retire_lat simd dso_from dso_to
                            symbol_from symbol_to mispredict abort in_tx cycles
                            srcline_from srcline_to ipc_lbr addr_from addr_to
                            symbol_daddr dso_daddr locked tlb mem snoop dcacheline
                            symbol_iaddr phys_daddr data_page_size blocked
  #

After:

  # perf report --stdio -s type
  # To display the perf.data header info, please use --header/--header-only options.
  #
  #
  # Total Lost Samples: 0
  #
  # Samples: 4  of event 'cpu_atom/mem-loads,ldlat=30/P'
  # Event count (approx.): 7
  #
  # Overhead  Data Type
  # ........  .........
  #
     100.00%  (unknown)

  #
  # (Tip: Print event counts in CSV format with: perf stat -x,)
  #
  # rpm -q kernel-debuginfo
  kernel-debuginfo-6.6.4-200.fc39.x86_64
  # uname -r
  6.6.4-200.fc39.x86_64
  #
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: linux-toolchains@vger.kernel.org>
Cc: linux-trace-devel@vger.kernel.org>
Link: https://lore.kernel.org/r/20231213001323.718046-9-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 67bc54bb
...@@ -118,6 +118,7 @@ OPTIONS ...@@ -118,6 +118,7 @@ OPTIONS
- retire_lat: On X86, this reports pipeline stall of this instruction compared - retire_lat: On X86, this reports pipeline stall of this instruction compared
to the previous instruction in cycles. And currently supported only on X86 to the previous instruction in cycles. And currently supported only on X86
- simd: Flags describing a SIMD operation. "e" for empty Arm SVE predicate. "p" for partial Arm SVE predicate - simd: Flags describing a SIMD operation. "e" for empty Arm SVE predicate. "p" for partial Arm SVE predicate
- type: Data type of sample memory access.
By default, comm, dso and symbol keys are used. By default, comm, dso and symbol keys are used.
(i.e. --sort comm,dso,symbol) (i.e. --sort comm,dso,symbol)
......
...@@ -22,6 +22,8 @@ struct annotated_data_type { ...@@ -22,6 +22,8 @@ struct annotated_data_type {
int type_size; int type_size;
}; };
extern struct annotated_data_type unknown_type;
#ifdef HAVE_DWARF_SUPPORT #ifdef HAVE_DWARF_SUPPORT
/* Returns data type at the location (ip, reg, offset) */ /* Returns data type at the location (ip, reg, offset) */
......
...@@ -82,6 +82,7 @@ enum hist_column { ...@@ -82,6 +82,7 @@ enum hist_column {
HISTC_ADDR_TO, HISTC_ADDR_TO,
HISTC_ADDR, HISTC_ADDR,
HISTC_SIMD, HISTC_SIMD,
HISTC_TYPE,
HISTC_NR_COLS, /* Last entry */ HISTC_NR_COLS, /* Last entry */
}; };
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "strbuf.h" #include "strbuf.h"
#include "mem-events.h" #include "mem-events.h"
#include "annotate.h" #include "annotate.h"
#include "annotate-data.h"
#include "event.h" #include "event.h"
#include "time-utils.h" #include "time-utils.h"
#include "cgroup.h" #include "cgroup.h"
...@@ -2094,7 +2095,7 @@ struct sort_entry sort_dso_size = { ...@@ -2094,7 +2095,7 @@ struct sort_entry sort_dso_size = {
.se_width_idx = HISTC_DSO_SIZE, .se_width_idx = HISTC_DSO_SIZE,
}; };
/* --sort dso_size */ /* --sort addr */
static int64_t static int64_t
sort__addr_cmp(struct hist_entry *left, struct hist_entry *right) sort__addr_cmp(struct hist_entry *left, struct hist_entry *right)
...@@ -2131,6 +2132,69 @@ struct sort_entry sort_addr = { ...@@ -2131,6 +2132,69 @@ struct sort_entry sort_addr = {
.se_width_idx = HISTC_ADDR, .se_width_idx = HISTC_ADDR,
}; };
/* --sort type */
struct annotated_data_type unknown_type = {
.type_name = (char *)"(unknown)",
};
static int64_t
sort__type_cmp(struct hist_entry *left, struct hist_entry *right)
{
return sort__addr_cmp(left, right);
}
static void sort__type_init(struct hist_entry *he)
{
if (he->mem_type)
return;
he->mem_type = hist_entry__get_data_type(he);
if (he->mem_type == NULL)
he->mem_type = &unknown_type;
}
static int64_t
sort__type_collapse(struct hist_entry *left, struct hist_entry *right)
{
struct annotated_data_type *left_type = left->mem_type;
struct annotated_data_type *right_type = right->mem_type;
if (!left_type) {
sort__type_init(left);
left_type = left->mem_type;
}
if (!right_type) {
sort__type_init(right);
right_type = right->mem_type;
}
return strcmp(left_type->type_name, right_type->type_name);
}
static int64_t
sort__type_sort(struct hist_entry *left, struct hist_entry *right)
{
return sort__type_collapse(left, right);
}
static int hist_entry__type_snprintf(struct hist_entry *he, char *bf,
size_t size, unsigned int width)
{
return repsep_snprintf(bf, size, "%-*s", width, he->mem_type->type_name);
}
struct sort_entry sort_type = {
.se_header = "Data Type",
.se_cmp = sort__type_cmp,
.se_collapse = sort__type_collapse,
.se_sort = sort__type_sort,
.se_init = sort__type_init,
.se_snprintf = hist_entry__type_snprintf,
.se_width_idx = HISTC_TYPE,
};
struct sort_dimension { struct sort_dimension {
const char *name; const char *name;
...@@ -2185,7 +2249,8 @@ static struct sort_dimension common_sort_dimensions[] = { ...@@ -2185,7 +2249,8 @@ static struct sort_dimension common_sort_dimensions[] = {
DIM(SORT_ADDR, "addr", sort_addr), DIM(SORT_ADDR, "addr", sort_addr),
DIM(SORT_LOCAL_RETIRE_LAT, "local_retire_lat", sort_local_p_stage_cyc), DIM(SORT_LOCAL_RETIRE_LAT, "local_retire_lat", sort_local_p_stage_cyc),
DIM(SORT_GLOBAL_RETIRE_LAT, "retire_lat", sort_global_p_stage_cyc), DIM(SORT_GLOBAL_RETIRE_LAT, "retire_lat", sort_global_p_stage_cyc),
DIM(SORT_SIMD, "simd", sort_simd) DIM(SORT_SIMD, "simd", sort_simd),
DIM(SORT_ANNOTATE_DATA_TYPE, "type", sort_type),
}; };
#undef DIM #undef DIM
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
struct option; struct option;
struct thread; struct thread;
struct annotated_data_type;
extern regex_t parent_regex; extern regex_t parent_regex;
extern const char *sort_order; extern const char *sort_order;
...@@ -34,6 +35,7 @@ extern struct sort_entry sort_dso_to; ...@@ -34,6 +35,7 @@ extern struct sort_entry sort_dso_to;
extern struct sort_entry sort_sym_from; extern struct sort_entry sort_sym_from;
extern struct sort_entry sort_sym_to; extern struct sort_entry sort_sym_to;
extern struct sort_entry sort_srcline; extern struct sort_entry sort_srcline;
extern struct sort_entry sort_type;
extern const char default_mem_sort_order[]; extern const char default_mem_sort_order[];
extern bool chk_double_cl; extern bool chk_double_cl;
...@@ -154,6 +156,7 @@ struct hist_entry { ...@@ -154,6 +156,7 @@ struct hist_entry {
struct perf_hpp_list *hpp_list; struct perf_hpp_list *hpp_list;
struct hist_entry *parent_he; struct hist_entry *parent_he;
struct hist_entry_ops *ops; struct hist_entry_ops *ops;
struct annotated_data_type *mem_type;
union { union {
/* this is for hierarchical entry structure */ /* this is for hierarchical entry structure */
struct { struct {
...@@ -243,6 +246,7 @@ enum sort_type { ...@@ -243,6 +246,7 @@ enum sort_type {
SORT_LOCAL_RETIRE_LAT, SORT_LOCAL_RETIRE_LAT,
SORT_GLOBAL_RETIRE_LAT, SORT_GLOBAL_RETIRE_LAT,
SORT_SIMD, SORT_SIMD,
SORT_ANNOTATE_DATA_TYPE,
/* branch stack specific sort keys */ /* branch stack specific sort keys */
__SORT_BRANCH_STACK, __SORT_BRANCH_STACK,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment