lkml.org 
[lkml]   [2011]   [Jul]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4/4] perf, tool: Add new command "perf mem"
    Date
    Adds new command "perf mem" to monitor memory load/store events.

    $ perf mem

    usage: perf mem [<options>] {record <command> |report}

    -t, --type <type> memory operations(load/store)
    -L, --latency <n> latency to sample(only for load op)

    Signed-off-by: Lin Ming <ming.m.lin@intel.com>
    ---
    tools/perf/Makefile | 1 +
    tools/perf/builtin-record.c | 8 ++++++++
    tools/perf/builtin-script.c | 6 +++---
    tools/perf/builtin.h | 1 +
    tools/perf/perf.c | 1 +
    tools/perf/util/event.h | 2 ++
    tools/perf/util/evsel.c | 10 ++++++++++
    tools/perf/util/parse-events.c | 40 ++++++++++++++++++++++++++++++++++------
    tools/perf/util/parse-events.h | 2 +-
    9 files changed, 61 insertions(+), 10 deletions(-)

    diff --git a/tools/perf/Makefile b/tools/perf/Makefile
    index 032ba63..221d1d8 100644
    --- a/tools/perf/Makefile
    +++ b/tools/perf/Makefile
    @@ -372,6 +372,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
    BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
    BUILTIN_OBJS += $(OUTPUT)builtin-test.o
    BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
    +BUILTIN_OBJS += $(OUTPUT)builtin-mem.o

    PERFLIBS = $(LIB_FILE)

    diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
    index 8e2c857..8ebdcdd 100644
    --- a/tools/perf/builtin-record.c
    +++ b/tools/perf/builtin-record.c
    @@ -63,6 +63,7 @@ static bool inherit_stat = false;
    static bool no_samples = false;
    static bool sample_address = false;
    static bool sample_time = false;
    +static bool latency_data = false;
    static bool no_buildid = false;
    static bool no_buildid_cache = false;
    static struct perf_evlist *evsel_list;
    @@ -199,6 +200,11 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
    attr->mmap_data = track;
    }

    + if (latency_data) {
    + attr->sample_type |= PERF_SAMPLE_LATENCY;
    + attr->sample_type |= PERF_SAMPLE_EXTRA;
    + }
    +
    if (call_graph)
    attr->sample_type |= PERF_SAMPLE_CALLCHAIN;

    @@ -780,6 +786,8 @@ const struct option record_options[] = {
    OPT_BOOLEAN('T', "timestamp", &sample_time, "Sample timestamps"),
    OPT_BOOLEAN('n', "no-samples", &no_samples,
    "don't sample"),
    + OPT_BOOLEAN('l', "latency", &latency_data,
    + "Latency data"),
    OPT_BOOLEAN('N', "no-buildid-cache", &no_buildid_cache,
    "do not update the buildid cache"),
    OPT_BOOLEAN('B', "no-buildid", &no_buildid,
    diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
    index 3056b45..c7489a6 100644
    --- a/tools/perf/builtin-script.c
    +++ b/tools/perf/builtin-script.c
    @@ -140,7 +140,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,
    return 0;

    if (output[type].user_set) {
    - evname = __event_name(attr->type, attr->config);
    + evname = __event_name(attr->type, attr->config, attr->config1);
    pr_err("Samples for '%s' event do not have %s attribute set. "
    "Cannot print '%s' field.\n",
    evname, sample_msg, output_field2str(field));
    @@ -149,7 +149,7 @@ static int perf_event_attr__check_stype(struct perf_event_attr *attr,

    /* user did not ask for it explicitly so remove from the default list */
    output[type].fields &= ~field;
    - evname = __event_name(attr->type, attr->config);
    + evname = __event_name(attr->type, attr->config, attr->config1);
    pr_debug("Samples for '%s' event do not have %s attribute set. "
    "Skipping '%s' field.\n",
    evname, sample_msg, output_field2str(field));
    @@ -292,7 +292,7 @@ static void print_sample_start(struct perf_sample *sample,
    if (event)
    evname = event->name;
    } else
    - evname = __event_name(attr->type, attr->config);
    + evname = __event_name(attr->type, attr->config, 0);

    printf("%s: ", evname ? evname : "(unknown)");
    }
    diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
    index 4702e24..419ba8f 100644
    --- a/tools/perf/builtin.h
    +++ b/tools/perf/builtin.h
    @@ -36,5 +36,6 @@ extern int cmd_lock(int argc, const char **argv, const char *prefix);
    extern int cmd_kvm(int argc, const char **argv, const char *prefix);
    extern int cmd_test(int argc, const char **argv, const char *prefix);
    extern int cmd_inject(int argc, const char **argv, const char *prefix);
    +extern int cmd_mem(int argc, const char **argv, const char *prefix);

    #endif
    diff --git a/tools/perf/perf.c b/tools/perf/perf.c
    index ec635b7..20c53f8 100644
    --- a/tools/perf/perf.c
    +++ b/tools/perf/perf.c
    @@ -332,6 +332,7 @@ static void handle_internal_command(int argc, const char **argv)
    { "kvm", cmd_kvm, 0 },
    { "test", cmd_test, 0 },
    { "inject", cmd_inject, 0 },
    + { "mem", cmd_mem, 0 },
    };
    unsigned int i;
    static const char ext[] = STRIP_EXTENSION;
    diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
    index 1d7f664..1392867 100644
    --- a/tools/perf/util/event.h
    +++ b/tools/perf/util/event.h
    @@ -76,6 +76,8 @@ struct perf_sample {
    u64 id;
    u64 stream_id;
    u64 period;
    + u64 latency;
    + u64 extra;
    u32 cpu;
    u32 raw_size;
    void *raw_data;
    diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
    index a03a36b..8eab351 100644
    --- a/tools/perf/util/evsel.c
    +++ b/tools/perf/util/evsel.c
    @@ -405,6 +405,16 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
    array++;
    }

    + if (type & PERF_SAMPLE_LATENCY) {
    + data->latency = *array;
    + array++;
    + }
    +
    + if (type & PERF_SAMPLE_EXTRA) {
    + data->extra = *array;
    + array++;
    + }
    +
    if (type & PERF_SAMPLE_READ) {
    fprintf(stderr, "PERF_SAMPLE_READ is unsuported for now\n");
    return -1;
    diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
    index 41982c3..9f3bcb9 100644
    --- a/tools/perf/util/parse-events.c
    +++ b/tools/perf/util/parse-events.c
    @@ -40,6 +40,8 @@ static struct event_symbol event_symbols[] = {
    { CHW(BRANCH_INSTRUCTIONS), "branch-instructions", "branches" },
    { CHW(BRANCH_MISSES), "branch-misses", "" },
    { CHW(BUS_CYCLES), "bus-cycles", "" },
    + { CHW(MEM_LOAD), "mem-load", "" },
    + { CHW(MEM_STORE), "mem-store", "" },

    { CSW(CPU_CLOCK), "cpu-clock", "" },
    { CSW(TASK_CLOCK), "task-clock", "" },
    @@ -297,15 +299,18 @@ const char *event_name(struct perf_evsel *evsel)
    if (evsel->name)
    return evsel->name;

    - return __event_name(type, config);
    + return __event_name(type, config, evsel->attr.config1);
    }

    -const char *__event_name(int type, u64 config)
    +const char *__event_name(int type, u64 config, u64 extra)
    {
    static char buf[32];
    + int n;

    if (type == PERF_TYPE_RAW) {
    - sprintf(buf, "raw 0x%" PRIx64, config);
    + n = sprintf(buf, "raw 0x%" PRIx64, config);
    + if (extra)
    + sprintf(buf + n, ":%#" PRIx64, extra);
    return buf;
    }

    @@ -668,6 +673,7 @@ static enum event_result
    parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
    {
    const char *str = *strp;
    + u64 config;
    unsigned int i;
    int n;

    @@ -676,7 +682,18 @@ parse_symbolic_event(const char **strp, struct perf_event_attr *attr)
    if (n > 0) {
    attr->type = event_symbols[i].type;
    attr->config = event_symbols[i].config;
    - *strp = str + n;
    + str += n;
    + *strp = str;
    +
    + if (*str++ == ':') {
    + n = hex2u64(str + 1, &config);
    + if (n > 0) {
    + attr->config1 = config;
    + str += n + 1;
    + *strp = str;
    + }
    + }
    +
    return EVT_HANDLED;
    }
    }
    @@ -694,9 +711,20 @@ parse_raw_event(const char **strp, struct perf_event_attr *attr)
    return EVT_FAILED;
    n = hex2u64(str + 1, &config);
    if (n > 0) {
    - *strp = str + n + 1;
    + str += n + 1;
    + *strp = str;
    attr->type = PERF_TYPE_RAW;
    attr->config = config;
    +
    + if (*str++ == ':') {
    + n = hex2u64(str + 1, &config);
    + if (n > 0) {
    + attr->config1 = config;
    + str += n + 1;
    + *strp = str;
    + }
    + }
    +
    return EVT_HANDLED;
    }
    return EVT_FAILED;
    @@ -1078,7 +1106,7 @@ void print_events(const char *event_glob)

    printf("\n");
    printf(" %-50s [%s]\n",
    - "rNNN (see 'perf list --help' on how to encode it)",
    + "rNNN[:EEE] (see 'perf list --help' on how to encode it)",
    event_type_descriptors[PERF_TYPE_RAW]);
    printf("\n");

    diff --git a/tools/perf/util/parse-events.h b/tools/perf/util/parse-events.h
    index 746d3fc..904c8c4 100644
    --- a/tools/perf/util/parse-events.h
    +++ b/tools/perf/util/parse-events.h
    @@ -22,7 +22,7 @@ extern bool have_tracepoints(struct list_head *evlist);

    const char *event_type(int type);
    const char *event_name(struct perf_evsel *event);
    -extern const char *__event_name(int type, u64 config);
    +extern const char *__event_name(int type, u64 config, u64 extra);

    extern int parse_events(const struct option *opt, const char *str, int unset);
    extern int parse_filter(const struct option *opt, const char *str, int unset);
    --
    1.7.5.1


    \
     
     \ /
      Last update: 2011-07-04 09:59    [W:0.034 / U:0.348 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site