perf/core: Add weighted samples
authorAndi Kleen <ak@linux.intel.com>
Thu, 24 Jan 2013 15:10:28 +0000 (16:10 +0100)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Mon, 1 Apr 2013 15:15:44 +0000 (12:15 -0300)
For some events it's useful to weight sample with a hardware
provided number. This expresses how expensive the action the
sample represent was.  This allows the profiler to scale
the samples to be more informative to the programmer.

There is already the period which is used similarly, but it
means something different, so I chose to not overload it.
Instead a new sample type for WEIGHT is added.

Can be used for multiple things. Initially it is used for TSX
abort costs and profiling by memory latencies (so to make
expensive load appear higher up in the histograms). The concept
is quite generic and can be extended to many other kinds of
events or architectures, as long as the hardware provides
suitable auxillary values. In principle it could be also used
for software tracepoints.

This adds the generic glue. A new optional sample format for a
64-bit weight value.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Stephane Eranian <eranian@google.com>
Cc: peterz@infradead.org
Cc: acme@redhat.com
Cc: jolsa@redhat.com
Cc: namhyung.kim@lge.com
Link: http://lkml.kernel.org/r/1359040242-8269-5-git-send-email-eranian@google.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
include/linux/perf_event.h
include/uapi/linux/perf_event.h
kernel/events/core.c

index cd3bb2cd94940bf3dc1c007d61129b5ec7b86288..7ce0b37b155ba25bfddb2234194dcf1dce46f985 100644 (file)
@@ -573,6 +573,7 @@ struct perf_sample_data {
        struct perf_branch_stack        *br_stack;
        struct perf_regs_user           regs_user;
        u64                             stack_user_size;
+       u64                             weight;
 };
 
 static inline void perf_sample_data_init(struct perf_sample_data *data,
@@ -586,6 +587,7 @@ static inline void perf_sample_data_init(struct perf_sample_data *data,
        data->regs_user.abi = PERF_SAMPLE_REGS_ABI_NONE;
        data->regs_user.regs = NULL;
        data->stack_user_size = 0;
+       data->weight = 0;
 }
 
 extern void perf_output_sample(struct perf_output_handle *handle,
index 9fa9c622a7f45ab6032aefd74001930b4d7ddb07..cdc255da02e2d79e9f415d007c1dcefd8dff2cf5 100644 (file)
@@ -132,8 +132,10 @@ enum perf_event_sample_format {
        PERF_SAMPLE_BRANCH_STACK                = 1U << 11,
        PERF_SAMPLE_REGS_USER                   = 1U << 12,
        PERF_SAMPLE_STACK_USER                  = 1U << 13,
+       PERF_SAMPLE_WEIGHT                      = 1U << 14,
+
+       PERF_SAMPLE_MAX = 1U << 15,             /* non-ABI */
 
-       PERF_SAMPLE_MAX = 1U << 14,             /* non-ABI */
 };
 
 /*
@@ -588,6 +590,8 @@ enum perf_event_type {
         *      { u64                   size;
         *        char                  data[size];
         *        u64                   dyn_size; } && PERF_SAMPLE_STACK_USER
+        *
+        *      { u64                   weight;   } && PERF_SAMPLE_WEIGHT
         * };
         */
        PERF_RECORD_SAMPLE                      = 9,
index 7b4a55d41efc7f44db1885acb10d0edfd5045cd6..9e3edb272b3e756fbcb8dd8d78b0229b975964e0 100644 (file)
@@ -976,6 +976,9 @@ static void perf_event__header_size(struct perf_event *event)
        if (sample_type & PERF_SAMPLE_PERIOD)
                size += sizeof(data->period);
 
+       if (sample_type & PERF_SAMPLE_WEIGHT)
+               size += sizeof(data->weight);
+
        if (sample_type & PERF_SAMPLE_READ)
                size += event->read_size;
 
@@ -4193,6 +4196,9 @@ void perf_output_sample(struct perf_output_handle *handle,
                perf_output_sample_ustack(handle,
                                          data->stack_user_size,
                                          data->regs_user.regs);
+
+       if (sample_type & PERF_SAMPLE_WEIGHT)
+               perf_output_put(handle, data->weight);
 }
 
 void perf_prepare_sample(struct perf_event_header *header,