All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/4] VNC server memory savings
@ 2015-08-27 10:18 Peter Lieven
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two Peter Lieven
                   ` (3 more replies)
  0 siblings, 4 replies; 20+ messages in thread
From: Peter Lieven @ 2015-08-27 10:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Lieven, kraxel

While debugging increased memory footprint of Qemu (since qemu-kvm-1.2.0)
I found some culprits in the VNC code. This series includes some
first optimizations.

Peter Lieven (4):
  vnc: make the Buffer capacity increase in powers of two
  vnc: allow the Buffer to shrink again
  vnc-jobs: move buffer_reset to vnc_async_encoding_end
  vnc: destroy server surface if no client is connected

 ui/vnc-jobs.c |  3 +--
 ui/vnc.c      | 36 +++++++++++++++++++++++++++++++++---
 2 files changed, 34 insertions(+), 5 deletions(-)

-- 
1.9.1

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two
  2015-08-27 10:18 [Qemu-devel] [PATCH 0/4] VNC server memory savings Peter Lieven
@ 2015-08-27 10:18 ` Peter Lieven
  2015-09-03  8:56   ` Gerd Hoffmann
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again Peter Lieven
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-08-27 10:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Lieven, kraxel

This makes sure the number of reallocs is in O(log N).

Signed-off-by: Peter Lieven <pl@kamp.de>
---
 ui/vnc.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index caf82f5..8cfd2d8 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -653,10 +653,13 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
     vnc_write_s32(vs, encoding);
 }
 
+#define BUFFER_MIN_INIT_SIZE 4096
+
 void buffer_reserve(Buffer *buffer, size_t len)
 {
     if ((buffer->capacity - buffer->offset) < len) {
-        buffer->capacity += (len + 1024);
+        buffer->capacity = pow2ceil(buffer->capacity + len);
+        buffer->capacity = MAX(buffer->capacity, BUFFER_MIN_INIT_SIZE);
         buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
     }
 }
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-08-27 10:18 [Qemu-devel] [PATCH 0/4] VNC server memory savings Peter Lieven
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two Peter Lieven
@ 2015-08-27 10:18 ` Peter Lieven
  2015-08-27 10:39   ` Daniel P. Berrange
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 3/4] vnc-jobs: move buffer_reset to vnc_async_encoding_end Peter Lieven
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected Peter Lieven
  3 siblings, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-08-27 10:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Lieven, kraxel

currently the Buffer can only grow. This increases Qemu memory footprint
dramatically since normally the biggest VNC updates are at connection time.
But also after a VNC session has terminated there is one persistent buffer
in queue->buffer which I have seen to increase to over 100MB and it is never
getting smaller again.

Signed-off-by: Peter Lieven <pl@kamp.de>
---
 ui/vnc.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 8cfd2d8..061e337 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -654,6 +654,7 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
 }
 
 #define BUFFER_MIN_INIT_SIZE 4096
+#define BUFFER_MIN_SHRINK_SIZE 65536
 
 void buffer_reserve(Buffer *buffer, size_t len)
 {
@@ -674,9 +675,19 @@ uint8_t *buffer_end(Buffer *buffer)
     return buffer->buffer + buffer->offset;
 }
 
+static void buffer_shrink(Buffer *buffer) {
+    size_t new = MAX(pow2ceil(buffer->offset) * 2,
+                     BUFFER_MIN_SHRINK_SIZE);
+    if (new < buffer->capacity) {
+        buffer->buffer = g_realloc(buffer->buffer, new);
+        buffer->capacity = new;
+    }
+}
+
 void buffer_reset(Buffer *buffer)
 {
-        buffer->offset = 0;
+     buffer->offset = 0;
+     buffer_shrink(buffer);
 }
 
 void buffer_free(Buffer *buffer)
@@ -698,6 +709,7 @@ void buffer_advance(Buffer *buf, size_t len)
     memmove(buf->buffer, buf->buffer + len,
             (buf->offset - len));
     buf->offset -= len;
+    buffer_shrink(buf);
 }
 
 static void vnc_desktop_resize(VncState *vs)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 3/4] vnc-jobs: move buffer_reset to vnc_async_encoding_end
  2015-08-27 10:18 [Qemu-devel] [PATCH 0/4] VNC server memory savings Peter Lieven
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two Peter Lieven
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again Peter Lieven
@ 2015-08-27 10:18 ` Peter Lieven
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected Peter Lieven
  3 siblings, 0 replies; 20+ messages in thread
From: Peter Lieven @ 2015-08-27 10:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Lieven, kraxel

now that we are able to shrink the buffer it makes sense
to move the buffer_reset to vnc_async_encoding_end to
actually shrink the buffer when it is no longer used.

Signed-off-by: Peter Lieven <pl@kamp.de>
---
 ui/vnc-jobs.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
index 22c9abc..201d9b7 100644
--- a/ui/vnc-jobs.c
+++ b/ui/vnc-jobs.c
@@ -195,8 +195,6 @@ static void vnc_async_encoding_start(VncState *orig, VncState *local)
     local->zrle = orig->zrle;
     local->output =  queue->buffer;
     local->csock = -1; /* Don't do any network work on this thread */
-
-    buffer_reset(&local->output);
 }
 
 static void vnc_async_encoding_end(VncState *orig, VncState *local)
@@ -208,6 +206,7 @@ static void vnc_async_encoding_end(VncState *orig, VncState *local)
     orig->lossy_rect = local->lossy_rect;
 
     queue->buffer = local->output;
+    buffer_reset(&queue->buffer);
 }
 
 static int vnc_worker_thread_loop(VncJobQueue *queue)
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected
  2015-08-27 10:18 [Qemu-devel] [PATCH 0/4] VNC server memory savings Peter Lieven
                   ` (2 preceding siblings ...)
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 3/4] vnc-jobs: move buffer_reset to vnc_async_encoding_end Peter Lieven
@ 2015-08-27 10:18 ` Peter Lieven
  2015-09-03  9:57   ` Gerd Hoffmann
  3 siblings, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-08-27 10:18 UTC (permalink / raw)
  To: qemu-devel; +Cc: Peter Lieven, kraxel

if no client is connected there is no need to keep the server
surface. Throw it away and replace it with a dummy surface to
save memory.

Signed-off-by: Peter Lieven <pl@kamp.de>
---
 ui/vnc.c | 17 ++++++++++++++++-
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index 061e337..57f0e54 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -776,6 +776,11 @@ static void vnc_dpy_switch(DisplayChangeListener *dcl,
 
     vnc_abort_display_jobs(vd);
 
+    /* if no client is connected use a dummy surface */
+    if (QTAILQ_EMPTY(&vd->clients)) {
+        surface = qemu_create_displaysurface(0, 0);
+    }
+
     /* server surface */
     qemu_pixman_image_unref(vd->server);
     vd->ds = surface;
@@ -1263,6 +1268,9 @@ void vnc_disconnect_finish(VncState *vs)
 
     if (vs->initialized) {
         QTAILQ_REMOVE(&vs->vd->clients, vs, next);
+        if (QTAILQ_EMPTY(&vs->vd->clients)) {
+            vnc_dpy_switch(&vs->vd->dcl, NULL);
+        }
         qemu_remove_mouse_mode_change_notifier(&vs->mouse_mode_notifier);
     }
 
@@ -3083,6 +3091,7 @@ void vnc_init_state(VncState *vs)
 {
     vs->initialized = true;
     VncDisplay *vd = vs->vd;
+    bool first_client;
 
     vs->last_x = -1;
     vs->last_y = -1;
@@ -3095,9 +3104,15 @@ void vnc_init_state(VncState *vs)
     qemu_mutex_init(&vs->output_mutex);
     vs->bh = qemu_bh_new(vnc_jobs_bh, vs);
 
+    first_client = QTAILQ_EMPTY(&vd->clients);
     QTAILQ_INSERT_TAIL(&vd->clients, vs, next);
 
-    graphic_hw_update(vd->dcl.con);
+    if (first_client) {
+        /* set/restore the correct surface in the VNC server */
+        console_select(0);
+    } else {
+        graphic_hw_update(vd->dcl.con);
+    }
 
     vnc_write(vs, "RFB 003.008\n", 12);
     vnc_flush(vs);
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again Peter Lieven
@ 2015-08-27 10:39   ` Daniel P. Berrange
  2015-08-27 12:36     ` Peter Lieven
  2015-09-03  9:52     ` Gerd Hoffmann
  0 siblings, 2 replies; 20+ messages in thread
From: Daniel P. Berrange @ 2015-08-27 10:39 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel, kraxel

On Thu, Aug 27, 2015 at 12:18:52PM +0200, Peter Lieven wrote:
> currently the Buffer can only grow. This increases Qemu memory footprint
> dramatically since normally the biggest VNC updates are at connection time.
> But also after a VNC session has terminated there is one persistent buffer
> in queue->buffer which I have seen to increase to over 100MB and it is never
> getting smaller again.

Do you have any idea what caused the buffer to increase to 100MB in size
in the first place ? I would expect a full screen update would cause the
biggest buffer usage, and even for a 1920x1140 screen that should not
be anywhere near 100MB in size. IOW, i'm wondering if the 100MB usage
is symptomatic of a more serious bug somewhere else in the VNC code
that you're just masking you reducing buffer size afterwards.


Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-08-27 10:39   ` Daniel P. Berrange
@ 2015-08-27 12:36     ` Peter Lieven
  2015-09-03  9:52     ` Gerd Hoffmann
  1 sibling, 0 replies; 20+ messages in thread
From: Peter Lieven @ 2015-08-27 12:36 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: qemu-devel, kraxel

Am 27.08.2015 um 12:39 schrieb Daniel P. Berrange:
> On Thu, Aug 27, 2015 at 12:18:52PM +0200, Peter Lieven wrote:
>> currently the Buffer can only grow. This increases Qemu memory footprint
>> dramatically since normally the biggest VNC updates are at connection time.
>> But also after a VNC session has terminated there is one persistent buffer
>> in queue->buffer which I have seen to increase to over 100MB and it is never
>> getting smaller again.
> Do you have any idea what caused the buffer to increase to 100MB in size
> in the first place ? I would expect a full screen update would cause the
> biggest buffer usage, and even for a 1920x1140 screen that should not
> be anywhere near 100MB in size. IOW, i'm wondering if the 100MB usage
> is symptomatic of a more serious bug somewhere else in the VNC code
> that you're just masking you reducing buffer size afterwards.

Maybe my commit message was a bit unclear. The memory usage of all buffers
went up to 100MB. The issue with the Buffer is that its not shrinking and that
the date is effectivly in 3 Buffers before its transferred on the wire. Plus depending
on the encoding used there are even more internal buffers.

Peter

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two Peter Lieven
@ 2015-09-03  8:56   ` Gerd Hoffmann
  2015-09-03 10:29     ` Peter Lieven
  0 siblings, 1 reply; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03  8:56 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel

On Do, 2015-08-27 at 12:18 +0200, Peter Lieven wrote:
> This makes sure the number of reallocs is in O(log N).

Looks good, applied.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-08-27 10:39   ` Daniel P. Berrange
  2015-08-27 12:36     ` Peter Lieven
@ 2015-09-03  9:52     ` Gerd Hoffmann
  2015-09-03 10:07       ` Peter Lieven
  2015-09-03 10:36       ` Peter Lieven
  1 sibling, 2 replies; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03  9:52 UTC (permalink / raw)
  To: Daniel P. Berrange; +Cc: Peter Lieven, qemu-devel

[-- Attachment #1: Type: text/plain, Size: 1342 bytes --]

On Do, 2015-08-27 at 11:39 +0100, Daniel P. Berrange wrote:
> On Thu, Aug 27, 2015 at 12:18:52PM +0200, Peter Lieven wrote:
> > currently the Buffer can only grow. This increases Qemu memory footprint
> > dramatically since normally the biggest VNC updates are at connection time.
> > But also after a VNC session has terminated there is one persistent buffer
> > in queue->buffer which I have seen to increase to over 100MB and it is never
> > getting smaller again.
> 
> Do you have any idea what caused the buffer to increase to 100MB in size
> in the first place ? I would expect a full screen update would cause the
> biggest buffer usage, and even for a 1920x1140 screen that should not
> be anywhere near 100MB in size. IOW, i'm wondering if the 100MB usage
> is symptomatic of a more serious bug somewhere else in the VNC code
> that you're just masking you reducing buffer size afterwards.

Cooked up a buffer stats patch (attached).
Buffer sizes are nowhere near 100MB for me (as expected by Daniel).
Individual buffers are in the 1 -> 4 MB range (1920x1080), even summed
up this is more like 10 not 100 MB.

So, big question remains why they are that big for you?

Beside that I think it makes sense to have the shrinking logic in
buffer_reserve too so we don't have to add buffer_shrink calls all over
the place.

cheers,
  Gerd


[-- Attachment #2: 0001-debug-vnc-buffer-stats.patch --]
[-- Type: text/x-patch, Size: 3442 bytes --]

From e5d9353d02983db0081e44026767adf9f5a72832 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 3 Sep 2015 11:44:18 +0200
Subject: [PATCH] [debug] vnc buffer stats

---
 ui/vnc-jobs.c |  1 +
 ui/vnc.c      | 38 ++++++++++++++++++++++++++++++++++++++
 ui/vnc.h      |  2 ++
 3 files changed, 41 insertions(+)

diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c
index 22c9abc..1338771 100644
--- a/ui/vnc-jobs.c
+++ b/ui/vnc-jobs.c
@@ -302,6 +302,7 @@ static VncJobQueue *vnc_queue_init(void)
 
     qemu_cond_init(&queue->cond);
     qemu_mutex_init(&queue->mutex);
+    buffer_init(&queue->buffer, 0, "queue");
     QTAILQ_INIT(&queue->jobs);
     return queue;
 }
diff --git a/ui/vnc.c b/ui/vnc.c
index 7a17954..59be765 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -655,12 +655,29 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
 
 #define BUFFER_MIN_INIT_SIZE 4096
 
+void buffer_init(Buffer *buffer, int fd, const char *name)
+{
+    if (fd) {
+        buffer->name = g_strdup_printf("%d/%s", fd, name);
+    } else {
+        buffer->name = g_strdup(name);
+    }
+}
+
 void buffer_reserve(Buffer *buffer, size_t len)
 {
+    bool inc = false;
+
+    assert(buffer->name);
     if ((buffer->capacity - buffer->offset) < len) {
         buffer->capacity = pow2ceil(buffer->capacity + len);
         buffer->capacity = MAX(buffer->capacity, BUFFER_MIN_INIT_SIZE);
         buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
+        inc = true;
+    }
+    if (inc) {
+        fprintf(stderr, "%s: %-10s: %4zd kB\n", __func__,
+                buffer->name, buffer->capacity / 1024);
     }
 }
 
@@ -681,6 +698,7 @@ void buffer_reset(Buffer *buffer)
 
 void buffer_free(Buffer *buffer)
 {
+    fprintf(stderr, "%s: %s\n", __func__, buffer->name);
     g_free(buffer->buffer);
     buffer->offset = 0;
     buffer->capacity = 0;
@@ -3027,6 +3045,26 @@ static void vnc_connect(VncDisplay *vd, int csock,
     vs->csock = csock;
     vs->vd = vd;
 
+    buffer_init(&vs->input, vs->csock, "in");
+    buffer_init(&vs->output, vs->csock, "out");
+    buffer_init(&vs->ws_input, vs->csock, "w-in");
+    buffer_init(&vs->ws_output, vs->csock, "w-out");
+    buffer_init(&vs->jobs_buffer, vs->csock, "jobs");
+
+    buffer_init(&vs->tight.tight, vs->csock, "t-tight");
+    buffer_init(&vs->tight.zlib, vs->csock, "t-zlib");
+    buffer_init(&vs->tight.gradient, vs->csock, "t-gradient");
+#ifdef CONFIG_VNC_JPEG
+    buffer_init(&vs->tight.jpeg, vs->csock, "t-jpeg");
+#endif
+#ifdef CONFIG_VNC_PNG
+    buffer_init(&vs->tight.png, vs->csock, "t-png");
+#endif
+    buffer_init(&vs->zlib.zlib, vs->csock, "zlib");
+    buffer_init(&vs->zrle.zrle, vs->csock, "z-zrle");
+    buffer_init(&vs->zrle.fb, vs->csock, "z-fb");
+    buffer_init(&vs->zrle.zlib, vs->csock, "z-zlib");
+
     if (skipauth) {
 	vs->auth = VNC_AUTH_NONE;
 	vs->subauth = VNC_AUTH_INVALID;
diff --git a/ui/vnc.h b/ui/vnc.h
index 814d720..95878c3 100644
--- a/ui/vnc.h
+++ b/ui/vnc.h
@@ -57,6 +57,7 @@
 
 typedef struct Buffer
 {
+    char *name;
     size_t capacity;
     size_t offset;
     uint8_t *buffer;
@@ -539,6 +540,7 @@ void start_client_init(VncState *vs);
 void start_auth_vnc(VncState *vs);
 
 /* Buffer management */
+void buffer_init(Buffer *buffer, int fd, const char *name);
 void buffer_reserve(Buffer *buffer, size_t len);
 void buffer_reset(Buffer *buffer);
 void buffer_free(Buffer *buffer);
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected
  2015-08-27 10:18 ` [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected Peter Lieven
@ 2015-09-03  9:57   ` Gerd Hoffmann
  2015-09-03 10:08     ` Peter Lieven
  0 siblings, 1 reply; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03  9:57 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel

On Do, 2015-08-27 at 12:18 +0200, Peter Lieven wrote:
> if no client is connected there is no need to keep the server
> surface. Throw it away and replace it with a dummy surface to
> save memory.

No dummy surface please.  Just set vd->server = NULL.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-09-03  9:52     ` Gerd Hoffmann
@ 2015-09-03 10:07       ` Peter Lieven
  2015-09-03 11:52         ` Gerd Hoffmann
  2015-09-03 10:36       ` Peter Lieven
  1 sibling, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-09-03 10:07 UTC (permalink / raw)
  To: Gerd Hoffmann, Daniel P. Berrange; +Cc: qemu-devel

Am 03.09.2015 um 11:52 schrieb Gerd Hoffmann:
> On Do, 2015-08-27 at 11:39 +0100, Daniel P. Berrange wrote:
>> On Thu, Aug 27, 2015 at 12:18:52PM +0200, Peter Lieven wrote:
>>> currently the Buffer can only grow. This increases Qemu memory footprint
>>> dramatically since normally the biggest VNC updates are at connection time.
>>> But also after a VNC session has terminated there is one persistent buffer
>>> in queue->buffer which I have seen to increase to over 100MB and it is never
>>> getting smaller again.
>> Do you have any idea what caused the buffer to increase to 100MB in size
>> in the first place ? I would expect a full screen update would cause the
>> biggest buffer usage, and even for a 1920x1140 screen that should not
>> be anywhere near 100MB in size. IOW, i'm wondering if the 100MB usage
>> is symptomatic of a more serious bug somewhere else in the VNC code
>> that you're just masking you reducing buffer size afterwards.
> Cooked up a buffer stats patch (attached).
> Buffer sizes are nowhere near 100MB for me (as expected by Daniel).
> Individual buffers are in the 1 -> 4 MB range (1920x1080), even summed
> up this is more like 10 not 100 MB.
>
> So, big question remains why they are that big for you?

I will try the patch out. Thank you.

>
> Beside that I think it makes sense to have the shrinking logic in
> buffer_reserve too so we don't have to add buffer_shrink calls all over
> the place.

We need a possibility to shrink the buffer after it has been used.
Especially the queue->buffer.

Thanks,
Peter

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected
  2015-09-03  9:57   ` Gerd Hoffmann
@ 2015-09-03 10:08     ` Peter Lieven
  2015-09-03 10:54       ` Gerd Hoffmann
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-09-03 10:08 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Am 03.09.2015 um 11:57 schrieb Gerd Hoffmann:
> On Do, 2015-08-27 at 12:18 +0200, Peter Lieven wrote:
>> if no client is connected there is no need to keep the server
>> surface. Throw it away and replace it with a dummy surface to
>> save memory.
> No dummy surface please.  Just set vd->server = NULL.

I can do that, but I have to check for vd->server == NULL at some points then.

Peter

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two
  2015-09-03  8:56   ` Gerd Hoffmann
@ 2015-09-03 10:29     ` Peter Lieven
  2015-09-03 10:47       ` Gerd Hoffmann
  0 siblings, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-09-03 10:29 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Am 03.09.2015 um 10:56 schrieb Gerd Hoffmann:
> On Do, 2015-08-27 at 12:18 +0200, Peter Lieven wrote:
>> This makes sure the number of reallocs is in O(log N).
> Looks good, applied.
>

I think there is a small error. The new capacity should be calculated as follows:

diff --git a/ui/vnc.c b/ui/vnc.c
index 8cfd2d8..79d3ff3 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -658,7 +658,7 @@ void vnc_framebuffer_update(VncState *vs, int x, int y, int w, int h,
  void buffer_reserve(Buffer *buffer, size_t len)
  {
      if ((buffer->capacity - buffer->offset) < len) {
-        buffer->capacity = pow2ceil(buffer->capacity + len);
+        buffer->capacity = pow2ceil(buffer->offset + len);
          buffer->capacity = MAX(buffer->capacity, BUFFER_MIN_INIT_SIZE);
          buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
      }


BR,
Peter

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-09-03  9:52     ` Gerd Hoffmann
  2015-09-03 10:07       ` Peter Lieven
@ 2015-09-03 10:36       ` Peter Lieven
  2015-09-03 11:57         ` Gerd Hoffmann
  1 sibling, 1 reply; 20+ messages in thread
From: Peter Lieven @ 2015-09-03 10:36 UTC (permalink / raw)
  To: Gerd Hoffmann, Daniel P. Berrange; +Cc: qemu-devel

Am 03.09.2015 um 11:52 schrieb Gerd Hoffmann:
> On Do, 2015-08-27 at 11:39 +0100, Daniel P. Berrange wrote:
>> On Thu, Aug 27, 2015 at 12:18:52PM +0200, Peter Lieven wrote:
>>> currently the Buffer can only grow. This increases Qemu memory footprint
>>> dramatically since normally the biggest VNC updates are at connection time.
>>> But also after a VNC session has terminated there is one persistent buffer
>>> in queue->buffer which I have seen to increase to over 100MB and it is never
>>> getting smaller again.
>> Do you have any idea what caused the buffer to increase to 100MB in size
>> in the first place ? I would expect a full screen update would cause the
>> biggest buffer usage, and even for a 1920x1140 screen that should not
>> be anywhere near 100MB in size. IOW, i'm wondering if the 100MB usage
>> is symptomatic of a more serious bug somewhere else in the VNC code
>> that you're just masking you reducing buffer size afterwards.
> Cooked up a buffer stats patch (attached).
> Buffer sizes are nowhere near 100MB for me (as expected by Daniel).
> Individual buffers are in the 1 -> 4 MB range (1920x1080), even summed
> up this is more like 10 not 100 MB.
>
> So, big question remains why they are that big for you?

Simple case to create at least a reasonable allocation: -vga vmware and a client that prefers Hextile encoding.

~/git/qemu$ x86_64-softmmu/qemu-system-x86_64 -m 4096 -enable-kvm -cdrom  ~/Downloads/ubuntu-14.04.3-desktop-amd64.iso -k de -usb -device usb-tablet -nodefaults -serial null -parallel null -cpu Westmere,enforce -vga vmware -monitor stdio -vnc :0
QEMU 2.4.50 monitor - type 'help' for more information
(qemu) buffer_reserve: 11/out    :    4 kB
buffer_reserve: 11/in     :    4 kB
buffer_reserve: queue     :    4 kB
buffer_reserve: queue     :    8 kB
buffer_reserve: 11/jobs   :    8 kB
buffer_reserve: 11/out    :   16 kB
buffer_reserve: queue     :   16 kB
buffer_reserve: queue     :   32 kB
buffer_reserve: queue     :   64 kB
buffer_reserve: queue     :  128 kB
buffer_reserve: queue     :  256 kB
buffer_reserve: 11/jobs   :  256 kB
buffer_reserve: 11/out    :  256 kB
buffer_reserve: queue     :  512 kB
buffer_reserve: queue     : 1024 kB
buffer_reserve: queue     : 2048 kB
buffer_reserve: 11/jobs   : 2048 kB
buffer_reserve: 11/out    : 2048 kB
buffer_reserve: queue     : 4096 kB
buffer_reserve: queue     : 8192 kB
buffer_reserve: queue     : 16384 kB
buffer_reserve: 11/jobs   : 16384 kB
buffer_reserve: 11/out    : 16384 kB

Its not 100MB, but 50MB.

Same with Tight encoding:

(qemu) buffer_reserve: 11/out    :    4 kB
buffer_reserve: 11/in     :    4 kB
buffer_reserve: queue     :    4 kB
buffer_reserve: 11/t-tight:    4 kB
buffer_reserve: 11/t-tight:    8 kB
buffer_reserve: 11/t-tight:   16 kB
buffer_reserve: 11/t-tight:   32 kB
buffer_reserve: 11/t-tight:   64 kB
buffer_reserve: 11/t-tight:  128 kB
buffer_reserve: 11/t-tight:  256 kB
buffer_reserve: 11/t-tight:  512 kB
buffer_reserve: 11/t-zlib :    4 kB
buffer_reserve: 11/jobs   :    4 kB
buffer_reserve: 11/t-zlib :   64 kB
buffer_reserve: 11/t-tight: 1024 kB
buffer_reserve: 11/t-tight: 2048 kB
buffer_reserve: 11/t-tight: 4096 kB
buffer_reserve: 11/t-tight: 8192 kB
buffer_reserve: 11/t-tight: 16384 kB
buffer_reserve: 11/t-zlib :  128 kB
buffer_reserve: queue     :    8 kB
buffer_reserve: 11/jobs   :    8 kB
buffer_reserve: 11/out    :    8 kB
buffer_reserve: 11/t-zlib :  256 kB
buffer_reserve: queue     :   64 kB
buffer_reserve: queue     :  128 kB
buffer_reserve: queue     :  256 kB
buffer_reserve: queue     :  512 kB
buffer_reserve: queue     : 1024 kB
buffer_reserve: queue     : 2048 kB
buffer_reserve: queue     : 4096 kB
buffer_reserve: queue     : 8192 kB
buffer_reserve: 11/jobs   : 8192 kB
buffer_reserve: 11/out    : 8192 kB

~40MB.

Peter

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two
  2015-09-03 10:29     ` Peter Lieven
@ 2015-09-03 10:47       ` Gerd Hoffmann
  0 siblings, 0 replies; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03 10:47 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel

On Do, 2015-09-03 at 12:29 +0200, Peter Lieven wrote:
> -        buffer->capacity = pow2ceil(buffer->capacity + len);
> +        buffer->capacity = pow2ceil(buffer->offset + len);

Updated patch.

thanks,
  Gerd

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected
  2015-09-03 10:08     ` Peter Lieven
@ 2015-09-03 10:54       ` Gerd Hoffmann
  0 siblings, 0 replies; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03 10:54 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel

On Do, 2015-09-03 at 12:08 +0200, Peter Lieven wrote:
> Am 03.09.2015 um 11:57 schrieb Gerd Hoffmann:
> > On Do, 2015-08-27 at 12:18 +0200, Peter Lieven wrote:
> >> if no client is connected there is no need to keep the server
> >> surface. Throw it away and replace it with a dummy surface to
> >> save memory.
> > No dummy surface please.  Just set vd->server = NULL.
> 
> I can do that, but I have to check for vd->server == NULL at some points then.

Sure.  That'll shortcut code paths which should not have any effect
anyway.  You probably also want factor out server surface initialization
into a function which is called for both first vnc connect and surface
changes.

Oh, and btw: in case the surface changes without resolution/depth
changing (guest page flip) we might simply skip surface
(re-)initialization.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-09-03 10:07       ` Peter Lieven
@ 2015-09-03 11:52         ` Gerd Hoffmann
  2015-09-03 14:52           ` Peter Lieven
  0 siblings, 1 reply; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03 11:52 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 833 bytes --]

  Hi,

> > Beside that I think it makes sense to have the shrinking logic in
> > buffer_reserve too so we don't have to add buffer_shrink calls all over
> > the place.
> 
> We need a possibility to shrink the buffer after it has been used.
> Especially the queue->buffer.

That works fine.  Test patch attached.

I'm not sure this is the way to go though.  I see alot of growing and
shrinking.  We also do alot of coping (each realloc, but also from
buffer to buffer).

We might be better off redoing the whole buffer management, at least
once we are done with encoding one frame.  Passing on a *pointer* to the
buffer, once sent to the wire just free the buffer.  Allocate a new one
for the next frame.  That way we copy around less data and also don't
have to worry about big unused buffers in the first place ...

cheers,
  Gerd


[-- Attachment #2: 0001-test-buffer-shrink-in-buffer_reserve.patch --]
[-- Type: text/x-patch, Size: 1443 bytes --]

From caa6c3b78595343c651bf4db96dc25db0b163486 Mon Sep 17 00:00:00 2001
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 3 Sep 2015 13:41:39 +0200
Subject: [PATCH] [test] buffer shrink in buffer_reserve

---
 ui/vnc.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/ui/vnc.c b/ui/vnc.c
index aa6b0a5..728cbbe 100644
--- a/ui/vnc.c
+++ b/ui/vnc.c
@@ -667,6 +667,7 @@ void buffer_init(Buffer *buffer, int fd, const char *name)
 void buffer_reserve(Buffer *buffer, size_t len)
 {
     bool inc = false;
+    bool dec = false;
 
     assert(buffer->name);
     if ((buffer->capacity - buffer->offset) < len) {
@@ -675,9 +676,17 @@ void buffer_reserve(Buffer *buffer, size_t len)
         buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
         inc = true;
     }
-    if (inc) {
-        fprintf(stderr, "%s: %-10s: %4zd kB\n", __func__,
-                buffer->name, buffer->capacity / 1024);
+    if (((buffer->offset + len) < buffer->capacity >> 4) &&
+        (buffer->capacity > 64 * 1024)) {
+        buffer->capacity >>= 1;
+        buffer->capacity = MAX(buffer->capacity, 64 * 1024);
+        buffer->buffer = g_realloc(buffer->buffer, buffer->capacity);
+        dec = true;
+    }
+    if (inc || dec) {
+        fprintf(stderr, "%s: %-10s: %4zd kB %s\n", __func__,
+                buffer->name, buffer->capacity / 1024,
+                inc ? "+" : "-");
     }
 }
 
-- 
1.8.3.1


^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-09-03 10:36       ` Peter Lieven
@ 2015-09-03 11:57         ` Gerd Hoffmann
  2015-09-03 12:00           ` Peter Lieven
  0 siblings, 1 reply; 20+ messages in thread
From: Gerd Hoffmann @ 2015-09-03 11:57 UTC (permalink / raw)
  To: Peter Lieven; +Cc: qemu-devel

  Hi,

> buffer_reserve: 11/t-tight: 4096 kB
> buffer_reserve: 11/t-tight: 8192 kB
> buffer_reserve: 11/t-tight: 16384 kB

A bit more than what I see (4096 usually, 8192 once).  No idea why.

> buffer_reserve: queue     : 8192 kB
> buffer_reserve: 11/jobs   : 8192 kB
> buffer_reserve: 11/out    : 8192 kB

Noticeable more than what I see.

Is this local or remote client?  Maybe these stay smaller for me (local
client) simply because qemu can put the data to the wire faster.

cheers,
  Gerd

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-09-03 11:57         ` Gerd Hoffmann
@ 2015-09-03 12:00           ` Peter Lieven
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Lieven @ 2015-09-03 12:00 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Am 03.09.2015 um 13:57 schrieb Gerd Hoffmann:
>    Hi,
>
>> buffer_reserve: 11/t-tight: 4096 kB
>> buffer_reserve: 11/t-tight: 8192 kB
>> buffer_reserve: 11/t-tight: 16384 kB
> A bit more than what I see (4096 usually, 8192 once).  No idea why.
>
>> buffer_reserve: queue     : 8192 kB
>> buffer_reserve: 11/jobs   : 8192 kB
>> buffer_reserve: 11/out    : 8192 kB
> Noticeable more than what I see.
>
> Is this local or remote client?  Maybe these stay smaller for me (local
> client) simply because qemu can put the data to the wire faster.

Local. But maybe you don't have a fullscreen background image in
the vserver?

Peter

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again
  2015-09-03 11:52         ` Gerd Hoffmann
@ 2015-09-03 14:52           ` Peter Lieven
  0 siblings, 0 replies; 20+ messages in thread
From: Peter Lieven @ 2015-09-03 14:52 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Am 03.09.2015 um 13:52 schrieb Gerd Hoffmann:
>    Hi,
>
>>> Beside that I think it makes sense to have the shrinking logic in
>>> buffer_reserve too so we don't have to add buffer_shrink calls all over
>>> the place.
>> We need a possibility to shrink the buffer after it has been used.
>> Especially the queue->buffer.
> That works fine.  Test patch attached.

Not completely. queue->buffer may remain big, if you disconnect in the
wrong moment. Maybe there should be a buffer_free if the last client
disconnects?

In general I like your modified patch because the shrinking is slower than
in my version. for 64*1024 you should introduce a macro.

>
> I'm not sure this is the way to go though.  I see alot of growing and
> shrinking.  We also do alot of coping (each realloc, but also from
> buffer to buffer).
>
> We might be better off redoing the whole buffer management, at least
> once we are done with encoding one frame.  Passing on a *pointer* to the
> buffer, once sent to the wire just free the buffer.  Allocate a new one
> for the next frame.  That way we copy around less data and also don't
> have to worry about big unused buffers in the first place ...

Maybe this should be the permanent solution.

Peter

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2015-09-03 14:53 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-08-27 10:18 [Qemu-devel] [PATCH 0/4] VNC server memory savings Peter Lieven
2015-08-27 10:18 ` [Qemu-devel] [PATCH 1/4] vnc: make the Buffer capacity increase in powers of two Peter Lieven
2015-09-03  8:56   ` Gerd Hoffmann
2015-09-03 10:29     ` Peter Lieven
2015-09-03 10:47       ` Gerd Hoffmann
2015-08-27 10:18 ` [Qemu-devel] [PATCH 2/4] vnc: allow the Buffer to shrink again Peter Lieven
2015-08-27 10:39   ` Daniel P. Berrange
2015-08-27 12:36     ` Peter Lieven
2015-09-03  9:52     ` Gerd Hoffmann
2015-09-03 10:07       ` Peter Lieven
2015-09-03 11:52         ` Gerd Hoffmann
2015-09-03 14:52           ` Peter Lieven
2015-09-03 10:36       ` Peter Lieven
2015-09-03 11:57         ` Gerd Hoffmann
2015-09-03 12:00           ` Peter Lieven
2015-08-27 10:18 ` [Qemu-devel] [PATCH 3/4] vnc-jobs: move buffer_reset to vnc_async_encoding_end Peter Lieven
2015-08-27 10:18 ` [Qemu-devel] [PATCH 4/4] vnc: destroy server surface if no client is connected Peter Lieven
2015-09-03  9:57   ` Gerd Hoffmann
2015-09-03 10:08     ` Peter Lieven
2015-09-03 10:54       ` Gerd Hoffmann

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.