aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndi Kleen <ak@linux.intel.com>2013-01-24 10:10:28 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2013-04-01 11:15:44 -0400
commitc3feedf2aaf9ac8bad6f19f5d21e4ee0b4b87e9c (patch)
treefb383d4c8037d476b52c424a0a51b1e3c3c7614f
parent9fac2cf316b070ae43d2ae2525e381ff2d1d68aa (diff)
perf/core: Add weighted samples
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>
-rw-r--r--include/linux/perf_event.h2
-rw-r--r--include/uapi/linux/perf_event.h6
-rw-r--r--kernel/events/core.c6
3 files changed, 13 insertions, 1 deletions
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index cd3bb2cd9494..7ce0b37b155b 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -573,6 +573,7 @@ struct perf_sample_data {
573 struct perf_branch_stack *br_stack; 573 struct perf_branch_stack *br_stack;
574 struct perf_regs_user regs_user; 574 struct perf_regs_user regs_user;
575 u64 stack_user_size; 575 u64 stack_user_size;
576 u64 weight;
576}; 577};
577 578
578static inline void perf_sample_data_init(struct perf_sample_data *data, 579static 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,
586 data->regs_user.abi = PERF_SAMPLE_REGS_ABI_NONE; 587 data->regs_user.abi = PERF_SAMPLE_REGS_ABI_NONE;
587 data->regs_user.regs = NULL; 588 data->regs_user.regs = NULL;
588 data->stack_user_size = 0; 589 data->stack_user_size = 0;
590 data->weight = 0;
589} 591}
590 592
591extern void perf_output_sample(struct perf_output_handle *handle, 593extern void perf_output_sample(struct perf_output_handle *handle,
diff --git a/include/uapi/linux/perf_event.h b/include/uapi/linux/perf_event.h
index 9fa9c622a7f4..cdc255da02e2 100644
--- a/include/uapi/linux/perf_event.h
+++ b/include/uapi/linux/perf_event.h
@@ -132,8 +132,10 @@ enum perf_event_sample_format {
132 PERF_SAMPLE_BRANCH_STACK = 1U << 11, 132 PERF_SAMPLE_BRANCH_STACK = 1U << 11,
133 PERF_SAMPLE_REGS_USER = 1U << 12, 133 PERF_SAMPLE_REGS_USER = 1U << 12,
134 PERF_SAMPLE_STACK_USER = 1U << 13, 134 PERF_SAMPLE_STACK_USER = 1U << 13,
135 PERF_SAMPLE_WEIGHT = 1U << 14,
136
137 PERF_SAMPLE_MAX = 1U << 15, /* non-ABI */
135 138
136 PERF_SAMPLE_MAX = 1U << 14, /* non-ABI */
137}; 139};
138 140
139/* 141/*
@@ -588,6 +590,8 @@ enum perf_event_type {
588 * { u64 size; 590 * { u64 size;
589 * char data[size]; 591 * char data[size];
590 * u64 dyn_size; } && PERF_SAMPLE_STACK_USER 592 * u64 dyn_size; } && PERF_SAMPLE_STACK_USER
593 *
594 * { u64 weight; } && PERF_SAMPLE_WEIGHT
591 * }; 595 * };
592 */ 596 */
593 PERF_RECORD_SAMPLE = 9, 597 PERF_RECORD_SAMPLE = 9,
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 7b4a55d41efc..9e3edb272b3e 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -976,6 +976,9 @@ static void perf_event__header_size(struct perf_event *event)
976 if (sample_type & PERF_SAMPLE_PERIOD) 976 if (sample_type & PERF_SAMPLE_PERIOD)
977 size += sizeof(data->period); 977 size += sizeof(data->period);
978 978
979 if (sample_type & PERF_SAMPLE_WEIGHT)
980 size += sizeof(data->weight);
981
979 if (sample_type & PERF_SAMPLE_READ) 982 if (sample_type & PERF_SAMPLE_READ)
980 size += event->read_size; 983 size += event->read_size;
981 984
@@ -4193,6 +4196,9 @@ void perf_output_sample(struct perf_output_handle *handle,
4193 perf_output_sample_ustack(handle, 4196 perf_output_sample_ustack(handle,
4194 data->stack_user_size, 4197 data->stack_user_size,
4195 data->regs_user.regs); 4198 data->regs_user.regs);
4199
4200 if (sample_type & PERF_SAMPLE_WEIGHT)
4201 perf_output_put(handle, data->weight);
4196} 4202}
4197 4203
4198void perf_prepare_sample(struct perf_event_header *header, 4204void perf_prepare_sample(struct perf_event_header *header,