* [Qemu-devel] Reducing X communication bandwidth
@ 2004-07-10 8:45 Julian Seward
2004-07-10 9:10 ` Jan Dittmer
` (3 more replies)
0 siblings, 4 replies; 12+ messages in thread
From: Julian Seward @ 2004-07-10 8:45 UTC (permalink / raw)
To: qemu-devel
[-- Attachment #1: Type: text/plain, Size: 2079 bytes --]
QEMU is great, but one specific problem has made it unusable
for me so far. The (fast) machine I want to run QEMU on is not
the same as my (slow) machine which is on my desk. That is,
I want to do the usual X "export DISPLAY=someothermachine:0.0"
game.
These machines are connected by an old-fashioned 10 Mbit/sec
network, which you may argue is obsolete, but I would argue
represents reasonably the approximate bandwidth of 802.11b/g
LANs which are common now.
Anyway, QEMU from cvs is unusable like this, at least when
running WinXP or Win2K. The SDL layer (qemu/sdl.c) blasts
huge numbers of pixels across the network in response to even
the simplest graphical operations. Notably, moving the mouse
pointer is appalling, with an update rate of about twice per
second, which is hopeless.
The attached patch against sdl.c fixes this. It keeps a shadow
copy of video memory. When a request arrives at sdl_update()
to redraw an area, the area is compared against the shadow copy,
and only the parts that have really changed are passed to
SDL_UpdateRect(). The comparison is done at a granularity of
32x32 chunks of pixels.
Currently I have an XP session running for several hours.
Without the patch, 2.7 million of these 32x32 chunks would
have been transmitted across the network, whereas with it,
the number is reduced to 322000, a factor of 9 reduction.
This makes QEMU actually usable for me. The most dramatic
improvement is merely moving the mouse pointer, where
typically QEMU requests 32 such chunks to be drawn, but only
1 or 2 are actually necessary, massively improving mouse-pointer
responsiveness. Of course it brings no benefit if sdl_update
is constantly asked to draw a series of "new" images, but
that generally doesn't appear to be the case.
Given that currently QEMU is (imo) unusable unless X client
and server run on the same machine, I think this is a good
candidate for cvs. It may need to handle the case where
screen->format->BytesPerPixel != 4
I don't know if that situation happens or not, but the
patch is a good start.
J
[-- Attachment #2: remote_x_client.patch --]
[-- Type: text/x-diff, Size: 4777 bytes --]
Index: sdl.c
===================================================================
RCS file: /cvsroot/qemu/qemu/sdl.c,v
retrieving revision 1.15
diff -u -3 -p -r1.15 sdl.c
--- sdl.c 5 Jul 2004 22:13:07 -0000 1.15
+++ sdl.c 10 Jul 2004 08:14:05 -0000
@@ -33,6 +33,8 @@
#define CONFIG_SDL_GENERIC_KBD
#endif
+#include <assert.h>
+
static SDL_Surface *screen;
static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
static int last_vm_running;
@@ -41,10 +43,126 @@ static int gui_fullscreen;
static int gui_key_modifier_pressed;
static int gui_keysym;
+/* Mechanism to reduce the total amount of data transmitted to the X
+ server, often quite dramatically. Keep a shadow copy of video
+ memory in alt_pixels, and when asked to update a rectangle, used
+ the shadow copy to establish areas which are the same, and so do
+ not need updating.
+*/
+
+static int* alt_pixels = NULL;
+
+#define THRESH 32
+
+/* Return 1 if the area [x .. x+w-1, y .. y+w-1] is different from
+ the old version and so needs updating. */
+static int cmpArea ( int x, int y, unsigned int w, unsigned int h)
+{
+ int i, j;
+ unsigned int sll;
+ int* p1base = (int*)screen->pixels;
+ int* p2base = (int*)alt_pixels;
+ assert(screen->format->BytesPerPixel == 4);
+ sll = ((unsigned int)screen->pitch) >> 2;
+
+ for (j = y; j < y+h; j++) {
+ for (i = x; i < x+w; i++) {
+ if (p1base [j * sll +i] != p2base [j * sll +i])
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static void copyArea ( int x, int y, unsigned int w, unsigned int h)
+{
+ int i, j;
+ unsigned int sll;
+ int* p1base = (int*)screen->pixels;
+ int* p2base = (int*)alt_pixels;
+ assert(screen->format->BytesPerPixel == 4);
+ sll = ((unsigned int)screen->pitch) >> 2;
+ for (j = y; j < y+h; j++) {
+ for (i = x; i < x+w; i++) {
+ p2base [j * sll +i] = p1base [j * sll +i];
+ }
+ }
+}
+
+
+static void econoUpdate (DisplayState *ds, int x, int y,
+ unsigned int w, unsigned int h)
+{
+ static int tested_total = 0;
+ static int update_total = 0;
+
+ int xi, xj, xlim, yi, yj, ylim, ntest, nupd;
+ if (w == 0 || h == 0)
+ return;
+ xlim = x + w;
+ ylim = y + h;
+
+ ntest = nupd = 0;
+ for (xi = x; xi < xlim; xi += THRESH) {
+ xj = xi + THRESH;
+ if (xj > xlim) xj = xlim;
+ for (yi = y; yi < ylim; yi += THRESH) {
+ yj = yi + THRESH;
+ if (yj > ylim) yj = ylim;
+ if (xj-xi == 0 || yj-yi == 0)
+ continue;
+ ntest++;
+ if (cmpArea(xi, yi, xj-xi, yj-yi)) {
+ nupd++;
+ copyArea(xi, yi, xj-xi, yj-yi);
+ SDL_UpdateRect(screen, xi, yi, xj-xi, yj-yi);
+ }
+ }
+ }
+ tested_total += ntest;
+ update_total += nupd;
+ printf("(tested, updated): total (%d, %d), this time (%d, %d)\n",
+ tested_total, update_total, ntest, nupd);
+}
+
+
static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
{
- // printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
- SDL_UpdateRect(screen, x, y, w, h);
+ int warned = 0;
+ //printf("updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
+ // printf("Total Size %d %d\n", screen->w, screen->h);
+ //printf("BytesPerPixel %d\n", screen->format->BytesPerPixel);
+ //printf("pitch %d\n", screen->pitch);
+
+ if (screen->format->BytesPerPixel != 4
+ || screen->pitch != screen->w * screen->format->BytesPerPixel) {
+ if (!warned) {
+ warned = 1;
+ fprintf(stderr, "qemu: SDL update optimisation disabled\n"
+ " (wrong bits-per-pixel, or wrong pitch)\n");
+ }
+ SDL_UpdateRect(screen, x, y, w, h);
+ return;
+ }
+
+ assert(screen->pitch == screen->w * screen->format->BytesPerPixel);
+ assert(sizeof(int) == 4);
+ if (alt_pixels == NULL) {
+ /* First time through (at this resolution).
+ Copy entire screen. */
+ int i, word32s = screen->w * screen->h;
+ //printf("copying init screen\n");
+ alt_pixels = malloc(word32s * sizeof(int));
+ assert(alt_pixels);
+ for (i = 0; i < word32s; i++)
+ alt_pixels[i] = ((int*)(screen->pixels))[i];
+ SDL_UpdateRect(screen, x, y, w, h);
+ //printf("done\n");
+ } else {
+ assert(w >= 0);
+ assert(h >= 0);
+ econoUpdate(ds, x, y, w, h);
+ }
}
static void sdl_resize(DisplayState *ds, int w, int h)
@@ -53,6 +171,11 @@ static void sdl_resize(DisplayState *ds,
// printf("resizing to %d %d\n", w, h);
+ if (alt_pixels) {
+ free(alt_pixels);
+ alt_pixels = NULL;
+ }
+
flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
flags |= SDL_RESIZABLE;
if (gui_fullscreen)
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 8:45 [Qemu-devel] Reducing X communication bandwidth Julian Seward
@ 2004-07-10 9:10 ` Jan Dittmer
2004-07-11 10:15 ` Hetz Ben Hamo
2004-07-11 11:18 ` Julian Seward
2004-07-10 12:00 ` Brad Campbell
` (2 subsequent siblings)
3 siblings, 2 replies; 12+ messages in thread
From: Jan Dittmer @ 2004-07-10 9:10 UTC (permalink / raw)
To: jseward; +Cc: qemu-devel
Julian Seward wrote:
> Anyway, QEMU from cvs is unusable like this, at least when
> running WinXP or Win2K. The SDL layer (qemu/sdl.c) blasts
Great, you're running XP, I've tried to install XP SP1 German but it
fails in an infinite reboot loop after install (see an earlier mail from
me on this list).
So can you tell what command line you used and - most important - which
version of XP?
Thanks,
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 9:10 ` Jan Dittmer
@ 2004-07-11 10:15 ` Hetz Ben Hamo
2004-07-10 10:53 ` Jan Dittmer
2004-07-11 8:20 ` Jan Dittmer
2004-07-11 11:18 ` Julian Seward
1 sibling, 2 replies; 12+ messages in thread
From: Hetz Ben Hamo @ 2004-07-11 10:15 UTC (permalink / raw)
To: qemu-devel
> Great, you're running XP, I've tried to install XP SP1 German but it
> fails in an infinite reboot loop after install (see an earlier mail from
> me on this list).
> So can you tell what command line you used and - most important - which
> version of XP?
Had the same problem. I simply quit qemu and restarted it. Things went well
after that..
Thanks,
Hetz
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-11 10:15 ` Hetz Ben Hamo
@ 2004-07-10 10:53 ` Jan Dittmer
2004-07-11 8:20 ` Jan Dittmer
1 sibling, 0 replies; 12+ messages in thread
From: Jan Dittmer @ 2004-07-10 10:53 UTC (permalink / raw)
To: hetz; +Cc: qemu-devel
Hetz Ben Hamo wrote:
>>Great, you're running XP, I've tried to install XP SP1 German but it
>>fails in an infinite reboot loop after install (see an earlier mail from
>>me on this list).
>>So can you tell what command line you used and - most important - which
>>version of XP?
>
>
> Had the same problem. I simply quit qemu and restarted it. Things went well
> after that..
Done that multiple times, believe me. Also tried to specify 'Standard
PC' on installation (this F5 thingy).
I'm still in the loop ;-)
Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-11 10:15 ` Hetz Ben Hamo
2004-07-10 10:53 ` Jan Dittmer
@ 2004-07-11 8:20 ` Jan Dittmer
1 sibling, 0 replies; 12+ messages in thread
From: Jan Dittmer @ 2004-07-11 8:20 UTC (permalink / raw)
To: hetz; +Cc: qemu-devel
Hetz Ben Hamo wrote:
>>Great, you're running XP, I've tried to install XP SP1 German but it
>>fails in an infinite reboot loop after install (see an earlier mail from
>>me on this list).
>>So can you tell what command line you used and - most important - which
>>version of XP?
>
>
> Had the same problem. I simply quit qemu and restarted it. Things went well
> after that..
I just retested the whole thing with 0.6.0 - still the same.
So, question remains, did you try with or without service pack 1 ? Have
you had the home, professional or corporate edition?
And what command line did you use? Just want to get some data points.
Otherwise you could perhaps hint me, how to get the last instructions
qemu executes before the vm is rebooting?!
Btw. I just tried this under vnc, and it seems there is a bsod shortly
before rebooting, I was probably just able to see because of the latency
of vnc.
Thanks, Jan
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 9:10 ` Jan Dittmer
2004-07-11 10:15 ` Hetz Ben Hamo
@ 2004-07-11 11:18 ` Julian Seward
1 sibling, 0 replies; 12+ messages in thread
From: Julian Seward @ 2004-07-11 11:18 UTC (permalink / raw)
To: Jan Dittmer; +Cc: qemu-devel
On Saturday 10 July 2004 10:10, Jan Dittmer wrote:
> Julian Seward wrote:
> > Anyway, QEMU from cvs is unusable like this, at least when
> > running WinXP or Win2K. The SDL layer (qemu/sdl.c) blasts
>
> Great, you're running XP, I've tried to install XP SP1 German but it
> fails in an infinite reboot loop after install (see an earlier mail from
> me on this list).
> So can you tell what command line you used and - most important - which
> version of XP?
Well, the box says: Windows XP Professional, Version 2002.
And its the English version I assume.
J
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 8:45 [Qemu-devel] Reducing X communication bandwidth Julian Seward
2004-07-10 9:10 ` Jan Dittmer
@ 2004-07-10 12:00 ` Brad Campbell
2004-07-10 12:42 ` Julian Seward
2004-07-10 13:53 ` Fabrice Bellard
2004-07-11 9:53 ` Johannes Schindelin
3 siblings, 1 reply; 12+ messages in thread
From: Brad Campbell @ 2004-07-10 12:00 UTC (permalink / raw)
To: jseward, qemu-devel
Julian Seward wrote:
> QEMU is great, but one specific problem has made it unusable
> for me so far. The (fast) machine I want to run QEMU on is not
> the same as my (slow) machine which is on my desk. That is,
> I want to do the usual X "export DISPLAY=someothermachine:0.0"
> game.
>
> These machines are connected by an old-fashioned 10 Mbit/sec
> network, which you may argue is obsolete, but I would argue
> represents reasonably the approximate bandwidth of 802.11b/g
> LANs which are common now.
>
> Anyway, QEMU from cvs is unusable like this, at least when
> running WinXP or Win2K. The SDL layer (qemu/sdl.c) blasts
> huge numbers of pixels across the network in response to even
> the simplest graphical operations. Notably, moving the mouse
> pointer is appalling, with an update rate of about twice per
> second, which is hopeless.
>
Great patch! This patch combined with ssh -X -C makes qemu usable over my wireless link between
office and home. Still a little laggy but at least usable.
Cheers!
Brad
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 12:00 ` Brad Campbell
@ 2004-07-10 12:42 ` Julian Seward
0 siblings, 0 replies; 12+ messages in thread
From: Julian Seward @ 2004-07-10 12:42 UTC (permalink / raw)
To: Brad Campbell; +Cc: qemu-devel
> > Anyway, QEMU from cvs is unusable like this, at least when
> > running WinXP or Win2K. The SDL layer (qemu/sdl.c) blasts
> > huge numbers of pixels across the network in response to even
> > the simplest graphical operations. Notably, moving the mouse
> > pointer is appalling, with an update rate of about twice per
> > second, which is hopeless.
>
> Great patch! This patch combined with ssh -X -C makes qemu usable over my
> wireless link between office and home. Still a little laggy but at least
> usable.
Cool.
You might want to experiment with the THRESH value in sdl.c
to get the best performance. I set it to 32 and that works
pretty well for me, but I'm not claiming it's optimal -- I
only tried 16 and 32, and 32 was better. You can use
any value >= 1. It controls the size of the blocks of
pixels over which the patch makes send/no-send decisions.
J
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 8:45 [Qemu-devel] Reducing X communication bandwidth Julian Seward
2004-07-10 9:10 ` Jan Dittmer
2004-07-10 12:00 ` Brad Campbell
@ 2004-07-10 13:53 ` Fabrice Bellard
2004-07-11 9:53 ` Johannes Schindelin
3 siblings, 0 replies; 12+ messages in thread
From: Fabrice Bellard @ 2004-07-10 13:53 UTC (permalink / raw)
To: jseward, qemu-devel
Julian Seward wrote:
> [...]
> Anyway, QEMU from cvs is unusable like this, at least when
> running WinXP or Win2K. The SDL layer (qemu/sdl.c) blasts
> huge numbers of pixels across the network in response to even
> the simplest graphical operations. Notably, moving the mouse
> pointer is appalling, with an update rate of about twice per
> second, which is hopeless.
>
> The attached patch against sdl.c fixes this. It keeps a shadow
> copy of video memory. When a request arrives at sdl_update()
> to redraw an area, the area is compared against the shadow copy,
> and only the parts that have really changed are passed to
> SDL_UpdateRect(). The comparison is done at a granularity of
> 32x32 chunks of pixels.
> [...]
OK for the feature.
I just want to be sure it does not slow down the case where QEMU runs
locally (comparisons may be slower than just copying). So there should
be a specific support to detect if shared memory is used by SDL.
Another point is that it may not be necessary to add a second frame
buffer. By modifying the vga core a single line of memory should be
necessary to do the comparison.
Fabrice.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-10 8:45 [Qemu-devel] Reducing X communication bandwidth Julian Seward
` (2 preceding siblings ...)
2004-07-10 13:53 ` Fabrice Bellard
@ 2004-07-11 9:53 ` Johannes Schindelin
2004-07-11 11:22 ` Julian Seward
3 siblings, 1 reply; 12+ messages in thread
From: Johannes Schindelin @ 2004-07-11 9:53 UTC (permalink / raw)
To: jseward, qemu-devel
Hi,
On Sat, 10 Jul 2004, Julian Seward wrote:
> The attached patch against sdl.c fixes this. It keeps a shadow
> copy of video memory. When a request arrives at sdl_update()
> to redraw an area, the area is compared against the shadow copy,
> and only the parts that have really changed are passed to
> SDL_UpdateRect(). The comparison is done at a granularity of
> 32x32 chunks of pixels.
Why does this remind me of VNC? In fact, that kind of application is the
exact reason I started my VNC patch. It could also be useful as a Windows
98 Terminal Server...
Ciao,
Dscho
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-11 9:53 ` Johannes Schindelin
@ 2004-07-11 11:22 ` Julian Seward
2004-07-12 10:16 ` Johannes Schindelin
0 siblings, 1 reply; 12+ messages in thread
From: Julian Seward @ 2004-07-11 11:22 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: qemu-devel
On Sunday 11 July 2004 10:53, Johannes Schindelin wrote:
> Hi,
>
> On Sat, 10 Jul 2004, Julian Seward wrote:
> > The attached patch against sdl.c fixes this. It keeps a shadow
> > copy of video memory. When a request arrives at sdl_update()
> > to redraw an area, the area is compared against the shadow copy,
> > and only the parts that have really changed are passed to
> > SDL_UpdateRect(). The comparison is done at a granularity of
> > 32x32 chunks of pixels.
>
> Why does this remind me of VNC? In fact, that kind of application is the
> exact reason I started my VNC patch. It could also be useful as a Windows
> 98 Terminal Server...
Exactly -- I got the idea from VNC. First I noticed that using qemu
just as a remote X client gave appalling performance *but* when you
run it on a remote VNC server and connect with vncviewer, the results
is quite usable. That immediately suggests that vnc found a lot of
redundant screen updates and did not bother to send them over the
network, and at that point I started hacking :-)
J
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [Qemu-devel] Reducing X communication bandwidth
2004-07-11 11:22 ` Julian Seward
@ 2004-07-12 10:16 ` Johannes Schindelin
0 siblings, 0 replies; 12+ messages in thread
From: Johannes Schindelin @ 2004-07-12 10:16 UTC (permalink / raw)
To: qemu-devel
Hi,
On Sun, 11 Jul 2004, Julian Seward wrote:
> Exactly -- I got the idea from VNC. First I noticed that using qemu
> just as a remote X client gave appalling performance *but* when you
> run it on a remote VNC server and connect with vncviewer, the results
> is quite usable. That immediately suggests that vnc found a lot of
> redundant screen updates and did not bother to send them over the
> network, and at that point I started hacking :-)
Not so. VNC does not yet find anything redundant. It just sends what vl.c
tells it to send. The problem more likely lies in SDL in that it does not
update the regions of the screen which have to be updated, but more than
that. Or maybe it is too eager to update so it sends much too often the
updated regions.
Ciao,
Dscho
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2004-07-12 10:18 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-07-10 8:45 [Qemu-devel] Reducing X communication bandwidth Julian Seward
2004-07-10 9:10 ` Jan Dittmer
2004-07-11 10:15 ` Hetz Ben Hamo
2004-07-10 10:53 ` Jan Dittmer
2004-07-11 8:20 ` Jan Dittmer
2004-07-11 11:18 ` Julian Seward
2004-07-10 12:00 ` Brad Campbell
2004-07-10 12:42 ` Julian Seward
2004-07-10 13:53 ` Fabrice Bellard
2004-07-11 9:53 ` Johannes Schindelin
2004-07-11 11:22 ` Julian Seward
2004-07-12 10:16 ` Johannes Schindelin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).