The dynticks code in qemu sets and gets timers very often. These
are the system calls (strace -c) of qemu/kvm running an idle Linux
kernel at 250Hz for 10 seconds:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.67 0.014391 1 23248 3187 ioctl
0.33 0.000047 0 43643 clock_gettime
0.00 0.000000 0 6375 gettimeofday
0.00 0.000000 0 6708 select
0.00 0.000000 0 3187 rt_sigaction
0.00 0.000000 0 9562 6375 rt_sigtimedwait
0.00 0.000000 0 10311 timer_settime
0.00 0.000000 0 12750 timer_gettime
------ ----------- ----------- --------- --------- ----------------
100.00 0.014438 115784 9562 total
The qemu_rearm_alarm_timer() function looks at vm_clock as well as
rt_clock timers, but is called from qemu_run_timers() which looks at
just one queue.
When an rt_clock timer has expired, the vm_clock iteration will rearm
with MIN_TIMER_REARM_US. This is not needed, since the timer in question
will be removed right away when qemu_run_timers() is run on the rt_clock
queue.
Moving the rearm call to after the two calls of qemu_run_timers() helps
a lot:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
99.74 0.012590 1 22766 2706 ioctl
0.26 0.000033 0 27044 clock_gettime
0.00 0.000000 0 5413 gettimeofday
0.00 0.000000 0 5745 select
0.00 0.000000 0 2706 rt_sigaction
0.00 0.000000 0 8119 5413 rt_sigtimedwait
0.00 0.000000 0 5215 timer_settime
0.00 0.000000 0 5413 timer_gettime
------ ----------- ----------- --------- --------- ----------------
100.00 0.012623 82421 8119 total
Patch (based on kvm-userspace git) attached.
Cheers,
Anders.
diff --git a/qemu/vl.c b/qemu/vl.c
index 80ceb2f..2cd580d 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -1063,7 +1063,6 @@ static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
/* run the callback (the timer list can be modified) */
ts->cb(ts->opaque);
}
- qemu_rearm_alarm_timer(alarm_timer);
}
int64_t qemu_get_clock(QEMUClock *clock)
@@ -7216,6 +7215,8 @@ void main_loop_wait(int timeout)
qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
qemu_get_clock(rt_clock));
+ qemu_rearm_alarm_timer(alarm_timer);
+
/* Check bottom-halves last in case any of the earlier events triggered
them. */
qemu_bh_poll();