lkml.org 
[lkml]   [2023]   [Nov]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 22/52] perf report: Add 'typeoff' sort key
    Date
    The typeoff sort key shows the data type name, offset and the name of
    the field. This is useful to see which field in the struct is accessed
    most frequently.

    $ perf report -s type,typeoff --hierarchy --stdio
    ...
    # Overhead Data Type / Data Type Offset
    # ............ ............................
    #
    ...
    1.23% struct cfs_rq
    0.19% struct cfs_rq +404 (throttle_count)
    0.19% struct cfs_rq +0 (load.weight)
    0.19% struct cfs_rq +336 (leaf_cfs_rq_list.next)
    0.09% struct cfs_rq +272 (propagate)
    0.09% struct cfs_rq +196 (removed.nr)
    0.09% struct cfs_rq +80 (curr)
    0.09% struct cfs_rq +544 (lt_b_children_throttled)
    0.06% struct cfs_rq +320 (rq)

    Signed-off-by: Namhyung Kim <namhyung@kernel.org>
    ---
    tools/perf/Documentation/perf-report.txt | 1 +
    tools/perf/util/annotate.c | 1 +
    tools/perf/util/hist.h | 1 +
    tools/perf/util/sort.c | 83 +++++++++++++++++++++++-
    tools/perf/util/sort.h | 2 +
    5 files changed, 87 insertions(+), 1 deletion(-)

    diff --git a/tools/perf/Documentation/perf-report.txt b/tools/perf/Documentation/perf-report.txt
    index aec34417090b..b57eb51b47aa 100644
    --- a/tools/perf/Documentation/perf-report.txt
    +++ b/tools/perf/Documentation/perf-report.txt
    @@ -119,6 +119,7 @@ OPTIONS
    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
    - type: Data type of sample memory access.
    + - typeoff: Offset in the data type of sample memory access.

    By default, comm, dso and symbol keys are used.
    (i.e. --sort comm,dso,symbol)
    diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
    index 049d6ba394bd..76309f1e6e39 100644
    --- a/tools/perf/util/annotate.c
    +++ b/tools/perf/util/annotate.c
    @@ -3717,6 +3717,7 @@ struct annotated_data_type *hist_entry__get_data_type(struct hist_entry *he)
    op_loc->offset,
    he->stat.nr_events,
    he->stat.period);
    + he->mem_type_off = op_loc->offset;
    return mem_type;
    }
    return NULL;
    diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
    index 9bfed867f288..941176afcebc 100644
    --- a/tools/perf/util/hist.h
    +++ b/tools/perf/util/hist.h
    @@ -83,6 +83,7 @@ enum hist_column {
    HISTC_ADDR,
    HISTC_SIMD,
    HISTC_TYPE,
    + HISTC_TYPE_OFFSET,
    HISTC_NR_COLS, /* Last entry */
    };

    diff --git a/tools/perf/util/sort.c b/tools/perf/util/sort.c
    index a41209e242ae..d78e680d3988 100644
    --- a/tools/perf/util/sort.c
    +++ b/tools/perf/util/sort.c
    @@ -2153,8 +2153,10 @@ static void sort__type_init(struct hist_entry *he)
    return;

    he->mem_type = hist_entry__get_data_type(he);
    - if (he->mem_type == NULL)
    + if (he->mem_type == NULL) {
    he->mem_type = &unknown_type;
    + he->mem_type_off = 0;
    + }
    }

    static int64_t
    @@ -2198,6 +2200,84 @@ struct sort_entry sort_type = {
    .se_width_idx = HISTC_TYPE,
    };

    +/* --sort typeoff */
    +
    +static int64_t
    +sort__typeoff_sort(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;
    + int64_t ret;
    +
    + if (!left_type) {
    + sort__type_init(left);
    + left_type = left->mem_type;
    + }
    +
    + if (!right_type) {
    + sort__type_init(right);
    + right_type = right->mem_type;
    + }
    +
    + ret = strcmp(left_type->self.type_name, right_type->self.type_name);
    + if (ret)
    + return ret;
    + return left->mem_type_off - right->mem_type_off;
    +}
    +
    +static void fill_member_name(char *buf, size_t sz, struct annotated_member *m,
    + int offset, bool first)
    +{
    + struct annotated_member *child;
    +
    + if (list_empty(&m->children))
    + return;
    +
    + list_for_each_entry(child, &m->children, node) {
    + if (child->offset <= offset && offset < child->offset + child->size) {
    + int len = 0;
    +
    + /* It can have anonymous struct/union members */
    + if (child->var_name) {
    + len = scnprintf(buf, sz, "%s%s",
    + first ? "" : ".", child->var_name);
    + first = false;
    + }
    +
    + fill_member_name(buf + len, sz - len, child, offset, first);
    + return;
    + }
    + }
    +}
    +
    +static int hist_entry__typeoff_snprintf(struct hist_entry *he, char *bf,
    + size_t size, unsigned int width __maybe_unused)
    +{
    + struct annotated_data_type *he_type = he->mem_type;
    + char buf[4096];
    +
    + buf[0] = '\0';
    + if (list_empty(&he_type->self.children))
    + snprintf(buf, sizeof(buf), "no field");
    + else
    + fill_member_name(buf, sizeof(buf), &he_type->self,
    + he->mem_type_off, true);
    + buf[4095] = '\0';
    +
    + return repsep_snprintf(bf, size, "%s %+d (%s)", he_type->self.type_name,
    + he->mem_type_off, buf);
    +}
    +
    +struct sort_entry sort_type_offset = {
    + .se_header = "Data Type Offset",
    + .se_cmp = sort__type_cmp,
    + .se_collapse = sort__typeoff_sort,
    + .se_sort = sort__typeoff_sort,
    + .se_init = sort__type_init,
    + .se_snprintf = hist_entry__typeoff_snprintf,
    + .se_width_idx = HISTC_TYPE_OFFSET,
    +};
    +

    struct sort_dimension {
    const char *name;
    @@ -2254,6 +2334,7 @@ static struct sort_dimension common_sort_dimensions[] = {
    DIM(SORT_GLOBAL_RETIRE_LAT, "retire_lat", sort_global_p_stage_cyc),
    DIM(SORT_SIMD, "simd", sort_simd),
    DIM(SORT_ANNOTATE_DATA_TYPE, "type", sort_type),
    + DIM(SORT_ANNOTATE_DATA_TYPE_OFFSET, "typeoff", sort_type_offset),
    };

    #undef DIM
    diff --git a/tools/perf/util/sort.h b/tools/perf/util/sort.h
    index aabf0b8331a3..d806adcc1e1e 100644
    --- a/tools/perf/util/sort.h
    +++ b/tools/perf/util/sort.h
    @@ -113,6 +113,7 @@ struct hist_entry {
    u64 p_stage_cyc;
    u8 cpumode;
    u8 depth;
    + int mem_type_off;
    struct simd_flags simd_flags;

    /* We are added by hists__add_dummy_entry. */
    @@ -247,6 +248,7 @@ enum sort_type {
    SORT_GLOBAL_RETIRE_LAT,
    SORT_SIMD,
    SORT_ANNOTATE_DATA_TYPE,
    + SORT_ANNOTATE_DATA_TYPE_OFFSET,

    /* branch stack specific sort keys */
    __SORT_BRANCH_STACK,
    --
    2.42.0.869.gea05f2083d-goog
    \
     
     \ /
      Last update: 2023-11-20 13:54    [W:5.392 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site