Skip to contentSkip to conversation

perf/core: addressing 4x slowdown during per-process profiling of STREAM benchmark on Intel Xeon Phi

PATCH Superseded Alexey Budankov 1 participant 1 message Jun 16, 2017 perf events

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore
#0 lore raw

PATCH v3 1/1 perf/core: addressing 4x slowdown during per-process profiling of STREAM benchmark on Intel Xeon Phi

perf/core: use context tstamp_data for skipped events on mux interrupt

By default, the userspace perf tool opens per-cpu task-bound events when sampling, so for N logical events requested by the user, the tool will open N * NR_CPUS events.

In the kernel, we mux events with a hrtimer, periodically rotating the
flexible group list and trying to schedule each group in turn. We skip groups whose cpu filter doesn't match. So when we get unlucky, we can walk N * (NR_CPUS - 1) groups pointlessly for each hrtimer invocation.

This has been observed to result in significant overhead when running the STREAM benchmark on 272 core Xeon Phi systems.

One way to avoid this is to place our events into an rb tree sorted by CPU filter, so that our hrtimer can skip to the current CPU's list and ignore everything else.

However skipped events still require its tstamp_* fields maintained properly on groups switching.

To implement that tstamp_data object is introduced at event context
so skipped events' tstamps would point to the object where timings are
updated only once by update_context_time() on every mux hrtimer interrupt. Thus iteration of skipped events can be avoided with its tstamp_* timings properly updated still.

Signed-off-by Alexey Budankov <[email protected]>

---
 include/linux/perf_event.h | 32 +++++++++++++++++---------
 kernel/events/core.c       | 56 
+++++++++++++++++++++++++++++-----------------
 2 files changed, 56 insertions(+), 32 deletions(-)
include/linux/perf_event.h +21 -11
index c9203d7..bb6e450 100644
@@ -550,6 +550,22 @@ struct pmu_event_list {
 	struct list_head	list;
 };
 
+struct perf_event_tstamp {
+	/*
+	 * These are timestamps used for computing total_time_enabled
+	 * and total_time_running when the event is in INACTIVE or
+	 * ACTIVE state, measured in nanoseconds from an arbitrary point
+	 * in time.
+	 * enabled: the notional time when the event was enabled
+	 * running: the notional time when the event was scheduled on
+	 * stopped: in INACTIVE state, the notional time when the
+	 *	event was scheduled off.
+	 */
+	u64 enabled;
+	u64 running;
+	u64 stopped;
+};
+
 /**
  * struct perf_event - performance event kernel representation:
  */
@@ -625,18 +641,11 @@ struct perf_event {
 	u64				total_time_running;
 
 	/*
-	 * These are timestamps used for computing total_time_enabled
-	 * and total_time_running when the event is in INACTIVE or
-	 * ACTIVE state, measured in nanoseconds from an arbitrary point
-	 * in time.
-	 * tstamp_enabled: the notional time when the event was enabled
-	 * tstamp_running: the notional time when the event was scheduled on
-	 * tstamp_stopped: in INACTIVE state, the notional time when the
-	 *	event was scheduled off.
+	 * tstamp points to the tstamp_data object below or to the object
+	 * located at the event context;
 	 */
-	u64				tstamp_enabled;
-	u64				tstamp_running;
-	u64				tstamp_stopped;
+	struct perf_event_tstamp	*tstamp;
+	struct perf_event_tstamp	tstamp_data;
 
 	/*
 	 * timestamp shadows the actual context timing but it can
@@ -772,6 +781,7 @@ struct perf_event_context {
 	 */
 	u64				time;
 	u64				timestamp;
+	struct perf_event_tstamp	tstamp_data;
 
 	/*
 	 * These fields let us detect when two contexts have both
kernel/events/core.c +35 -21

140 lines not on this page · raw message