lkml.org 
[lkml]   [2016]   [Sep]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 13/57] perf c2c report: Add dimension support
    Date
    Adding bare bones of dimension support for c2c report.

    Main interface functions are:
    c2c_hists__init
    c2c_hists__reinit

    which re/initialize 'struct c2c_hists' object with
    sort/display entries string, in a similar way that
    setup_sorting function does.

    We overload the dimension to provide multi line
    header support for sort/display entries.

    Also we overload base 'struct perf_hpp_fmt' object
    with 'struct c2c_fmt' to define c2c specific functions
    to deal with multi line headers and spans.

    Link: http://lkml.kernel.org/n/tip-yg8p7bc8p7grxg4eifs2als2@git.kernel.org
    Signed-off-by: Jiri Olsa <jolsa@kernel.org>
    ---
    tools/perf/builtin-c2c.c | 239 ++++++++++++++++++++++++++++++++++++++++++++++-
    1 file changed, 238 insertions(+), 1 deletion(-)

    diff --git a/tools/perf/builtin-c2c.c b/tools/perf/builtin-c2c.c
    index 3fac3a294bdd..63c0e2d8d2d8 100644
    --- a/tools/perf/builtin-c2c.c
    +++ b/tools/perf/builtin-c2c.c
    @@ -10,8 +10,14 @@
    #include "tool.h"
    #include "data.h"

    +struct c2c_hists {
    + struct hists hists;
    + struct perf_hpp_list list;
    +};
    +
    struct perf_c2c {
    - struct perf_tool tool;
    + struct perf_tool tool;
    + struct c2c_hists hists;
    };

    static struct perf_c2c c2c;
    @@ -28,6 +34,231 @@ static const char * const __usage_report[] = {

    static const char * const *report_c2c_usage = __usage_report;

    +#define C2C_HEADER_MAX 2
    +
    +struct c2c_header {
    + struct {
    + const char *text;
    + int span;
    + } line[C2C_HEADER_MAX];
    +};
    +
    +struct c2c_dimension {
    + struct c2c_header header;
    + const char *name;
    + int width;
    +
    + int64_t (*cmp)(struct perf_hpp_fmt *fmt,
    + struct hist_entry *, struct hist_entry *);
    + int (*entry)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
    + struct hist_entry *he);
    + int (*color)(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
    + struct hist_entry *he);
    +};
    +
    +struct c2c_fmt {
    + struct perf_hpp_fmt fmt;
    + struct c2c_dimension *dim;
    +};
    +
    +static int c2c_width(struct perf_hpp_fmt *fmt,
    + struct perf_hpp *hpp __maybe_unused,
    + struct hists *hists __maybe_unused)
    +{
    + struct c2c_fmt *c2c_fmt;
    +
    + c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
    + return c2c_fmt->dim->width;
    +}
    +
    +static int c2c_header(struct perf_hpp_fmt *fmt, struct perf_hpp *hpp,
    + struct hists *hists __maybe_unused, int line, int *span)
    +{
    + struct c2c_fmt *c2c_fmt;
    + struct c2c_dimension *dim;
    + int len = c2c_width(fmt, hpp, hists);
    + const char *text;
    +
    + c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
    + dim = c2c_fmt->dim;
    +
    + text = dim->header.line[line].text;
    + if (text == NULL)
    + text = "";
    +
    + if (*span) {
    + (*span)--;
    + return 0;
    + } else {
    + *span = dim->header.line[line].span;
    + }
    +
    + return scnprintf(hpp->buf, hpp->size, "%*s", len, text);
    +}
    +
    +static struct c2c_dimension *dimensions[] = {
    + NULL,
    +};
    +
    +static void fmt_free(struct perf_hpp_fmt *fmt)
    +{
    + struct c2c_fmt *c2c_fmt;
    +
    + c2c_fmt = container_of(fmt, struct c2c_fmt, fmt);
    + free(c2c_fmt);
    +}
    +
    +static bool fmt_equal(struct perf_hpp_fmt *a, struct perf_hpp_fmt *b)
    +{
    + struct c2c_fmt *c2c_a = container_of(a, struct c2c_fmt, fmt);
    + struct c2c_fmt *c2c_b = container_of(b, struct c2c_fmt, fmt);
    +
    + return c2c_a->dim == c2c_b->dim;
    +}
    +
    +static struct c2c_dimension *get_dimension(const char *name)
    +{
    + unsigned int i;
    +
    + for (i = 0; dimensions[i]; i++) {
    + struct c2c_dimension *dim = dimensions[i];
    +
    + if (!strcmp(dim->name, name))
    + return dim;
    + };
    +
    + return NULL;
    +}
    +
    +static struct c2c_fmt *get_format(const char *name)
    +{
    + struct c2c_dimension *dim = get_dimension(name);
    + struct c2c_fmt *c2c_fmt;
    + struct perf_hpp_fmt *fmt;
    +
    + if (!dim)
    + return NULL;
    +
    + c2c_fmt = zalloc(sizeof(*c2c_fmt));
    + if (!c2c_fmt)
    + return NULL;
    +
    + c2c_fmt->dim = dim;
    +
    + fmt = &c2c_fmt->fmt;
    + INIT_LIST_HEAD(&fmt->list);
    + INIT_LIST_HEAD(&fmt->sort_list);
    +
    + fmt->cmp = dim->cmp;
    + fmt->sort = dim->cmp;
    + fmt->entry = dim->entry;
    + fmt->header = c2c_header;
    + fmt->width = c2c_width;
    + fmt->collapse = dim->cmp;
    + fmt->equal = fmt_equal;
    + fmt->free = fmt_free;
    +
    + return c2c_fmt;
    +}
    +
    +static int c2c_hists__init_output(struct perf_hpp_list *hpp_list, char *name)
    +{
    + struct c2c_fmt *c2c_fmt = get_format(name);
    +
    + if (!c2c_fmt)
    + return -1;
    +
    + perf_hpp_list__column_register(hpp_list, &c2c_fmt->fmt);
    + return 0;
    +}
    +
    +static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name)
    +{
    + struct c2c_fmt *c2c_fmt = get_format(name);
    +
    + if (!c2c_fmt)
    + return -1;
    +
    + perf_hpp_list__register_sort_field(hpp_list, &c2c_fmt->fmt);
    + return 0;
    +}
    +
    +#define PARSE_LIST(_list, _fn) \
    + do { \
    + char *tmp, *tok; \
    + ret = 0; \
    + \
    + if (!_list) \
    + break; \
    + \
    + for (tok = strtok_r((char *)_list, ", ", &tmp); \
    + tok; tok = strtok_r(NULL, ", ", &tmp)) { \
    + ret = _fn(hpp_list, tok); \
    + if (ret == -EINVAL) { \
    + error("Invalid --fields key: `%s'", tok); \
    + break; \
    + } else if (ret == -ESRCH) { \
    + error("Unknown --fields key: `%s'", tok); \
    + break; \
    + } \
    + } \
    + } while (0)
    +
    +static int hpp_list__parse(struct perf_hpp_list *hpp_list,
    + const char *output_,
    + const char *sort_)
    +{
    + char *output = output_ ? strdup(output_) : NULL;
    + char *sort = sort_ ? strdup(sort_) : NULL;
    + int ret;
    +
    + PARSE_LIST(output, c2c_hists__init_output);
    + PARSE_LIST(sort, c2c_hists__init_sort);
    +
    + /* copy sort keys to output fields */
    + perf_hpp__setup_output_field(hpp_list);
    +
    + /*
    + * We dont need other sorting keys other than those
    + * we already specified. It also really slows down
    + * the processing a lot with big number of output
    + * fields, so switching this off for c2c.
    + */
    +
    +#if 0
    + /* and then copy output fields to sort keys */
    + perf_hpp__append_sort_keys(&hists->list);
    +#endif
    +
    + free(output);
    + free(sort);
    + return ret;
    +}
    +
    +static int c2c_hists__init(struct c2c_hists *hists,
    + const char *sort)
    +{
    + __hists__init(&hists->hists, &hists->list);
    +
    + /*
    + * Initialize only with sort fields, we need to resort
    + * later anyway, and that's where we add output fields
    + * as well.
    + */
    + perf_hpp_list__init(&hists->list);
    +
    + return hpp_list__parse(&hists->list, NULL, sort);
    +}
    +
    +__maybe_unused
    +static int c2c_hists__reinit(struct c2c_hists *c2c_hists,
    + const char *output,
    + const char *sort)
    +{
    + perf_hpp__reset_output_field(&c2c_hists->list);
    + return hpp_list__parse(&c2c_hists->list, output, sort);
    +}
    +
    static int perf_c2c__report(int argc, const char **argv)
    {
    struct perf_session *session;
    @@ -52,6 +283,12 @@ static int perf_c2c__report(int argc, const char **argv)

    file.path = input_name;

    + err = c2c_hists__init(&c2c.hists, "dcacheline");
    + if (err) {
    + pr_debug("Failed to initialize hists\n");
    + goto out;
    + }
    +
    session = perf_session__new(&file, 0, &c2c.tool);
    if (session == NULL) {
    pr_debug("No memory for session\n");
    --
    2.7.4
    \
     
     \ /
      Last update: 2016-09-23 00:03    [W:4.041 / U:0.400 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site