perf: Optimize hrtimer events
There is no need to re-initialize the hrtimer every time we start it, so don't do that (shaves a few cycles). Also, since we know hrtimers run at a fixed rate (nanoseconds) we can pre-compute the desired frequency at which they tick. This avoids us having to go through the whole adaptive frequency feedback logic (shaves another few cycles). Signed-off-by: Peter Zijlstra <a.p.zijlstra@chello.nl> LKML-Reference: <1297448589.5226.47.camel@laptop> Signed-off-by: Ingo Molnar <mingo@elte.hu>
This commit is contained in:
parent
163ec4354a
commit
ba3dd36c67
|
@ -5602,6 +5602,10 @@ static enum hrtimer_restart perf_swevent_hrtimer(struct hrtimer *hrtimer)
|
|||
u64 period;
|
||||
|
||||
event = container_of(hrtimer, struct perf_event, hw.hrtimer);
|
||||
|
||||
if (event->state != PERF_EVENT_STATE_ACTIVE)
|
||||
return HRTIMER_NORESTART;
|
||||
|
||||
event->pmu->read(event);
|
||||
|
||||
perf_sample_data_init(&data, 0);
|
||||
|
@ -5628,9 +5632,6 @@ static void perf_swevent_start_hrtimer(struct perf_event *event)
|
|||
if (!is_sampling_event(event))
|
||||
return;
|
||||
|
||||
hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
hwc->hrtimer.function = perf_swevent_hrtimer;
|
||||
|
||||
period = local64_read(&hwc->period_left);
|
||||
if (period) {
|
||||
if (period < 0)
|
||||
|
@ -5657,6 +5658,30 @@ static void perf_swevent_cancel_hrtimer(struct perf_event *event)
|
|||
}
|
||||
}
|
||||
|
||||
static void perf_swevent_init_hrtimer(struct perf_event *event)
|
||||
{
|
||||
struct hw_perf_event *hwc = &event->hw;
|
||||
|
||||
if (!is_sampling_event(event))
|
||||
return;
|
||||
|
||||
hrtimer_init(&hwc->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
|
||||
hwc->hrtimer.function = perf_swevent_hrtimer;
|
||||
|
||||
/*
|
||||
* Since hrtimers have a fixed rate, we can do a static freq->period
|
||||
* mapping and avoid the whole period adjust feedback stuff.
|
||||
*/
|
||||
if (event->attr.freq) {
|
||||
long freq = event->attr.sample_freq;
|
||||
|
||||
event->attr.sample_period = NSEC_PER_SEC / freq;
|
||||
hwc->sample_period = event->attr.sample_period;
|
||||
local64_set(&hwc->period_left, hwc->sample_period);
|
||||
event->attr.freq = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Software event: cpu wall time clock
|
||||
*/
|
||||
|
@ -5709,6 +5734,8 @@ static int cpu_clock_event_init(struct perf_event *event)
|
|||
if (event->attr.config != PERF_COUNT_SW_CPU_CLOCK)
|
||||
return -ENOENT;
|
||||
|
||||
perf_swevent_init_hrtimer(event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -5787,6 +5814,8 @@ static int task_clock_event_init(struct perf_event *event)
|
|||
if (event->attr.config != PERF_COUNT_SW_TASK_CLOCK)
|
||||
return -ENOENT;
|
||||
|
||||
perf_swevent_init_hrtimer(event);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue