* [Qemu-devel] [PATCH] Reduce redundant timer rearming
@ 2007-12-13 23:03 Anders
2007-12-13 23:17 ` Anders Melchiorsen
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Anders @ 2007-12-13 23:03 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 2227 bytes --]
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.
[-- Attachment #2: qemu-single-rearm.diff --]
[-- Type: text/x-patch, Size: 707 bytes --]
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();
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH] Reduce redundant timer rearming
2007-12-13 23:03 [Qemu-devel] [PATCH] Reduce redundant timer rearming Anders
@ 2007-12-13 23:17 ` Anders Melchiorsen
2007-12-13 23:29 ` [Qemu-devel] [PATCH 2] " Anders
2007-12-14 0:05 ` [Qemu-devel] [PATCH 3] " Anders
2 siblings, 0 replies; 5+ messages in thread
From: Anders Melchiorsen @ 2007-12-13 23:17 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1852 bytes --]
> % 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
Here is another patch that implements a dirty bit for the timer lists.
The bit is set when timers are modified or expire. Rearming clears the
bit (and only happens if it is set).
Numbers improve to this:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000013 0 21813 clock_gettime
0.00 0.000000 0 22789 2729 ioctl
0.00 0.000000 0 5459 gettimeofday
0.00 0.000000 0 5790 select
0.00 0.000000 0 2729 rt_sigaction
0.00 0.000000 0 8188 5459 rt_sigtimedwait
0.00 0.000000 0 2729 timer_settime
0.00 0.000000 0 2752 timer_gettime
------ ----------- ----------- --------- --------- ----------------
100.00 0.000013 72249 8188 total
I am not so sure about this one, so comments are appreciated.
Best regards,
Anders.
[-- Attachment #2: qemu-rearm-when-modified.diff --]
[-- Type: text/x-patch, Size: 1186 bytes --]
diff --git a/qemu/vl.c b/qemu/vl.c
index 2cd580d..924736e 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -816,6 +816,7 @@ struct qemu_alarm_timer {
};
#define ALARM_FLAG_DYNTICKS 0x1
+#define ALARM_FLAG_MODIFIED 0x2
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
{
@@ -827,6 +828,11 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
if (!alarm_has_dynticks(t))
return;
+ if (!(t->flags & ALARM_FLAG_MODIFIED))
+ return;
+
+ t->flags &= ~(ALARM_FLAG_MODIFIED);
+
t->rearm(t);
}
@@ -989,6 +995,8 @@ void qemu_del_timer(QEMUTimer *ts)
{
QEMUTimer **pt, *t;
+ alarm_timer->flags |= ALARM_FLAG_MODIFIED;
+
/* NOTE: this code must be signal safe because
qemu_timer_expired() can be called from a signal. */
pt = &active_timers[ts->clock->type];
@@ -1182,6 +1190,7 @@ static void host_alarm_handler(int host_signum)
#endif
CPUState *env = cpu_single_env;
if (env) {
+ alarm_timer->flags |= ALARM_FLAG_MODIFIED;
/* stop the currently executing cpu because a timer occured */
cpu_interrupt(env, CPU_INTERRUPT_EXIT);
#ifdef USE_KQEMU
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 2] Reduce redundant timer rearming
2007-12-13 23:03 [Qemu-devel] [PATCH] Reduce redundant timer rearming Anders
2007-12-13 23:17 ` Anders Melchiorsen
@ 2007-12-13 23:29 ` Anders
2007-12-14 0:05 ` [Qemu-devel] [PATCH 3] " Anders
2 siblings, 0 replies; 5+ messages in thread
From: Anders @ 2007-12-13 23:29 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1910 bytes --]
(resending with the subscribed sender address)
> % 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
Here is another patch that implements a dirty bit for the timer lists.
The bit is set when timers are modified or expire. Rearming clears the
bit (and only happens if it is set).
Numbers improve to this:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000013 0 21813 clock_gettime
0.00 0.000000 0 22789 2729 ioctl
0.00 0.000000 0 5459 gettimeofday
0.00 0.000000 0 5790 select
0.00 0.000000 0 2729 rt_sigaction
0.00 0.000000 0 8188 5459 rt_sigtimedwait
0.00 0.000000 0 2729 timer_settime
0.00 0.000000 0 2752 timer_gettime
------ ----------- ----------- --------- --------- ----------------
100.00 0.000013 72249 8188 total
I am not so sure about this one, so comments are appreciated.
Best regards,
Anders.
[-- Attachment #2: qemu-rearm-when-modified.diff --]
[-- Type: text/x-patch, Size: 1186 bytes --]
diff --git a/qemu/vl.c b/qemu/vl.c
index 2cd580d..924736e 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -816,6 +816,7 @@ struct qemu_alarm_timer {
};
#define ALARM_FLAG_DYNTICKS 0x1
+#define ALARM_FLAG_MODIFIED 0x2
static inline int alarm_has_dynticks(struct qemu_alarm_timer *t)
{
@@ -827,6 +828,11 @@ static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t)
if (!alarm_has_dynticks(t))
return;
+ if (!(t->flags & ALARM_FLAG_MODIFIED))
+ return;
+
+ t->flags &= ~(ALARM_FLAG_MODIFIED);
+
t->rearm(t);
}
@@ -989,6 +995,8 @@ void qemu_del_timer(QEMUTimer *ts)
{
QEMUTimer **pt, *t;
+ alarm_timer->flags |= ALARM_FLAG_MODIFIED;
+
/* NOTE: this code must be signal safe because
qemu_timer_expired() can be called from a signal. */
pt = &active_timers[ts->clock->type];
@@ -1182,6 +1190,7 @@ static void host_alarm_handler(int host_signum)
#endif
CPUState *env = cpu_single_env;
if (env) {
+ alarm_timer->flags |= ALARM_FLAG_MODIFIED;
/* stop the currently executing cpu because a timer occured */
cpu_interrupt(env, CPU_INTERRUPT_EXIT);
#ifdef USE_KQEMU
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 3] Reduce redundant timer rearming
2007-12-13 23:03 [Qemu-devel] [PATCH] Reduce redundant timer rearming Anders
2007-12-13 23:17 ` Anders Melchiorsen
2007-12-13 23:29 ` [Qemu-devel] [PATCH 2] " Anders
@ 2007-12-14 0:05 ` Anders
2007-12-16 15:46 ` [Qemu-devel] [PATCH 4] " Anders
2 siblings, 1 reply; 5+ messages in thread
From: Anders @ 2007-12-14 0:05 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]
The VGA refresh (a 33 Hz timer) is running even with -nographics,
apparently doing nothing. The vga_hw_update() call ends up just
returning, because the display depth is zero.
This patch removes the dummy refresh handler, and thus the GUI refresh
timer.
With an idle dyntick Linux guest in qemu/kvm, there are now only two
timers per second (those are from the rtc). Another 10 seconds strace:
% time seconds usecs/call calls errors syscall
------ ----------- ----------- --------- --------- ----------------
100.00 0.000012 0 3760 20 ioctl
0.00 0.000000 0 41 select
0.00 0.000000 0 20 rt_sigaction
0.00 0.000000 0 61 41 rt_sigtimedwait
0.00 0.000000 0 20 timer_settime
0.00 0.000000 0 20 timer_gettime
0.00 0.000000 0 162 clock_gettime
------ ----------- ----------- --------- --------- ----------------
100.00 0.000012 4084 61 total
Cheers,
Anders.
[-- Attachment #2: qemu-disable-dummy-vga-refresh.patch --]
[-- Type: text/x-patch, Size: 659 bytes --]
diff --git a/qemu/vl.c b/qemu/vl.c
index 30c9537..8d67314 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -4902,13 +4902,6 @@ static void dumb_resize(DisplayState *ds, int w, int h)
{
}
-static void dumb_refresh(DisplayState *ds)
-{
-#if defined(CONFIG_SDL)
- vga_hw_update();
-#endif
-}
-
static void dumb_display_init(DisplayState *ds)
{
ds->data = NULL;
@@ -4916,7 +4909,7 @@ static void dumb_display_init(DisplayState *ds)
ds->depth = 0;
ds->dpy_update = dumb_update;
ds->dpy_resize = dumb_resize;
- ds->dpy_refresh = dumb_refresh;
+ ds->dpy_refresh = NULL;
}
/***********************************************************/
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [Qemu-devel] [PATCH 4] Reduce redundant timer rearming
2007-12-14 0:05 ` [Qemu-devel] [PATCH 3] " Anders
@ 2007-12-16 15:46 ` Anders
0 siblings, 0 replies; 5+ messages in thread
From: Anders @ 2007-12-16 15:46 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 384 bytes --]
The VNC output runs two 33 Hz timers, one for calling vga_hw_update() in
dpy_refresh (from vl.c), and another for calling vnc_update_client().
This patch moves the vga_hw_update() call into vnc_update_client(),
removing the need for the dpy_refresh timer.
It also makes the remaining timer only fire when a client is actually
connected to the VNC server.
Best regards,
Anders.
[-- Attachment #2: qemu-dynamic-vnc-refresh.diff --]
[-- Type: text/x-patch, Size: 1569 bytes --]
--- a/qemu/vnc.c
+++ b/qemu/vnc.c
@@ -493,6 +493,8 @@ static void vnc_update_client(void *opaque)
int saved_offset;
int has_dirty = 0;
+ vga_hw_update();
+
vnc_set_bits(width_mask, (vs->width / 16), VNC_DIRTY_WORDS);
/* Walk through the dirty map and eliminate tiles that
@@ -566,22 +568,11 @@ static void vnc_update_client(void *opaque)
vnc_flush(vs);
}
- qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
-}
-static void vnc_timer_init(VncState *vs)
-{
- if (vs->timer == NULL) {
- vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
- qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock));
+ if (vs->csock != -1) {
+ qemu_mod_timer(vs->timer, qemu_get_clock(rt_clock) + VNC_REFRESH_INTERVAL);
}
-}
-static void vnc_dpy_refresh(DisplayState *ds)
-{
- VncState *vs = ds->opaque;
- vnc_timer_init(vs);
- vga_hw_update();
}
static int vnc_listen_poll(void *opaque)
@@ -1890,6 +1881,7 @@ static void vnc_listen_read(void *opaque)
vs->has_resize = 0;
vs->has_hextile = 0;
vs->ds->dpy_copy = NULL;
+ vnc_update_client(vs);
}
}
@@ -1923,10 +1915,12 @@ void vnc_display_init(DisplayState *ds)
if (!vs->kbd_layout)
exit(1);
+ vs->timer = qemu_new_timer(rt_clock, vnc_update_client, vs);
+
vs->ds->data = NULL;
vs->ds->dpy_update = vnc_dpy_update;
vs->ds->dpy_resize = vnc_dpy_resize;
- vs->ds->dpy_refresh = vnc_dpy_refresh;
+ vs->ds->dpy_refresh = NULL;
memset(vs->dirty_row, 0xFF, sizeof(vs->dirty_row));
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2007-12-16 15:46 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-12-13 23:03 [Qemu-devel] [PATCH] Reduce redundant timer rearming Anders
2007-12-13 23:17 ` Anders Melchiorsen
2007-12-13 23:29 ` [Qemu-devel] [PATCH 2] " Anders
2007-12-14 0:05 ` [Qemu-devel] [PATCH 3] " Anders
2007-12-16 15:46 ` [Qemu-devel] [PATCH 4] " Anders
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.