[Spice-devel] [PATCH 2/2] Optimise client pipe passing pipe position instead of data

Frediano Ziglio fziglio at redhat.com
Mon Sep 12 15:32:03 UTC 2016


This avoid to have the search the data scanning all the
queue changing the order of these operations from O(n) to O(1).

Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
---
 server/dcc-send.c           |  9 ++++-----
 server/dcc.c                | 20 +++++++++-----------
 server/dcc.h                |  2 +-
 server/red-channel-client.c | 32 +++++++++++++++++++++++++-------
 server/red-channel-client.h |  4 +++-
 5 files changed, 42 insertions(+), 25 deletions(-)

diff --git a/server/dcc-send.c b/server/dcc-send.c
index 8bcba77..a22ee0b 100644
--- a/server/dcc-send.c
+++ b/server/dcc-send.c
@@ -187,10 +187,9 @@ static int is_brush_lossy(RedChannelClient *rcc, SpiceBrush *brush,
     }
 }
 
-static RedPipeItem *dcc_get_tail(DisplayChannelClient *dcc)
+static GList *dcc_get_tail(DisplayChannelClient *dcc)
 {
-    GQueue *pipe = red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc));
-    return g_queue_peek_tail(pipe);
+    return red_channel_client_get_pipe(RED_CHANNEL_CLIENT(dcc))->tail;
 }
 
 static void red_display_add_image_to_pixmap_cache(RedChannelClient *rcc,
@@ -738,13 +737,13 @@ static void red_pipe_replace_rendered_drawables_with_images(DisplayChannelClient
         }
 
         image = dcc_add_surface_area_image(dcc, drawable->red_drawable->surface_id,
-                                           &drawable->red_drawable->bbox, pipe_item, TRUE);
+                                           &drawable->red_drawable->bbox, l, TRUE);
         resent_surface_ids[num_resent] = drawable->red_drawable->surface_id;
         resent_areas[num_resent] = drawable->red_drawable->bbox;
         num_resent++;
 
         spice_assert(image);
-        red_channel_client_pipe_remove_and_release(RED_CHANNEL_CLIENT(dcc), &dpi->dpi_pipe_item);
+        red_channel_client_pipe_remove_and_release_pos(RED_CHANNEL_CLIENT(dcc), l);
         pipe_item = &image->base;
     }
 }
diff --git a/server/dcc.c b/server/dcc.c
index 0d672df..ece37d9 100644
--- a/server/dcc.c
+++ b/server/dcc.c
@@ -68,8 +68,7 @@ int dcc_drawable_is_in_pipe(DisplayChannelClient *dcc, Drawable *drawable)
 int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface_id,
                                           int wait_if_used)
 {
-    GList *l;
-    RedPipeItem *item = NULL;
+    GList *l, *item_pos = NULL;
     int x;
     RedChannelClient *rcc;
 
@@ -78,15 +77,14 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
        no other drawable depends on them */
 
     rcc = RED_CHANNEL_CLIENT(dcc);
-    l = rcc->priv->pipe.head;
-    while (l != NULL) {
-        GList *cur = l;
+    for (l = rcc->priv->pipe.head; l != NULL; item_pos = NULL) {
         Drawable *drawable;
         RedDrawablePipeItem *dpi = NULL;
         int depend_found = FALSE;
+        RedPipeItem *item = l->data;
 
+        item_pos = l;
         l = l->next;
-        item = cur->data;
         if (item->type == RED_PIPE_ITEM_TYPE_DRAW) {
             dpi = SPICE_CONTAINEROF(item, RedDrawablePipeItem, dpi_pipe_item);
             drawable = dpi->drawable;
@@ -97,7 +95,7 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
         }
 
         if (drawable->surface_id == surface_id) {
-            red_channel_client_pipe_remove_and_release(rcc, item);
+            red_channel_client_pipe_remove_and_release_pos(rcc, item_pos);
             continue;
         }
 
@@ -122,8 +120,8 @@ int dcc_clear_surface_drawables_from_pipe(DisplayChannelClient *dcc, int surface
         return TRUE;
     }
 
-    if (item) {
-        return red_channel_client_wait_pipe_item_sent(RED_CHANNEL_CLIENT(dcc), item,
+    if (item_pos) {
+        return red_channel_client_wait_pipe_item_sent(RED_CHANNEL_CLIENT(dcc), item_pos,
                                                       COMMON_CLIENT_TIMEOUT);
     } else {
         /*
@@ -168,7 +166,7 @@ void dcc_create_surface(DisplayChannelClient *dcc, int surface_id)
 RedImageItem *dcc_add_surface_area_image(DisplayChannelClient *dcc,
                                          int surface_id,
                                          SpiceRect *area,
-                                         RedPipeItem *pos,
+                                         GList *pos,
                                          int can_lossy)
 {
     DisplayChannel *display = DCC_TO_DC(dcc);
@@ -219,7 +217,7 @@ RedImageItem *dcc_add_surface_area_image(DisplayChannelClient *dcc,
     }
 
     if (pos) {
-        red_channel_client_pipe_add_after(RED_CHANNEL_CLIENT(dcc), &item->base, pos);
+        red_channel_client_pipe_add_after_pos(RED_CHANNEL_CLIENT(dcc), &item->base, pos);
     } else {
         red_channel_client_pipe_add(RED_CHANNEL_CLIENT(dcc), &item->base);
     }
diff --git a/server/dcc.h b/server/dcc.h
index d08e413..7f93186 100644
--- a/server/dcc.h
+++ b/server/dcc.h
@@ -129,7 +129,7 @@ void                       dcc_push_surface_image                    (DisplayCha
 RedImageItem *             dcc_add_surface_area_image                (DisplayChannelClient *dcc,
                                                                       int surface_id,
                                                                       SpiceRect *area,
-                                                                      RedPipeItem *pos,
+                                                                      GList *pos,
                                                                       int can_lossy);
 void                       dcc_palette_cache_reset                   (DisplayChannelClient *dcc);
 void                       dcc_palette_cache_palette                 (DisplayChannelClient *dcc,
diff --git a/server/red-channel-client.c b/server/red-channel-client.c
index 89ab679..563d888 100644
--- a/server/red-channel-client.c
+++ b/server/red-channel-client.c
@@ -1311,20 +1311,29 @@ void red_channel_client_pipe_add_push(RedChannelClient *rcc, RedPipeItem *item)
     red_channel_client_push(rcc);
 }
 
+void red_channel_client_pipe_add_after_pos(RedChannelClient *rcc,
+                                           RedPipeItem *item,
+                                           GList *pos)
+{
+    spice_assert(pos);
+    if (!prepare_pipe_add(rcc, item)) {
+        return;
+    }
+
+    g_queue_insert_after(&rcc->priv->pipe, pos, item);
+}
+
 void red_channel_client_pipe_add_after(RedChannelClient *rcc,
                                        RedPipeItem *item,
                                        RedPipeItem *pos)
 {
-    GList *prev = NULL;
+    GList *prev;
 
     spice_assert(pos);
-    if (!prepare_pipe_add(rcc, item)) {
-        return;
-    }
     prev = g_queue_find(&rcc->priv->pipe, pos);
     g_return_if_fail(prev != NULL);
 
-    g_queue_insert_after(&rcc->priv->pipe, prev, item);
+    red_channel_client_pipe_add_after_pos(rcc, item, prev);
 }
 
 int red_channel_client_pipe_item_is_linked(RedChannelClient *rcc,
@@ -1523,7 +1532,7 @@ static void marker_pipe_item_free(RedPipeItem *base)
 
 /* TODO: more evil sync stuff. anything with the word wait in it's name. */
 int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
-                                           RedPipeItem *item,
+                                           GList *item_pos,
                                            int64_t timeout)
 {
     uint64_t end_time;
@@ -1543,7 +1552,7 @@ int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
                             marker_pipe_item_free);
     item_in_pipe = TRUE;
     mark_item->item_in_pipe = &item_in_pipe;
-    red_channel_client_pipe_add_after(rcc, &mark_item->base, item);
+    red_channel_client_pipe_add_after_pos(rcc, &mark_item->base, item_pos);
 
     if (red_channel_client_is_blocked(rcc)) {
         red_channel_client_receive(rcc);
@@ -1624,6 +1633,15 @@ void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc,
     }
 }
 
+void red_channel_client_pipe_remove_and_release_pos(RedChannelClient *rcc,
+                                                    GList *item_pos)
+{
+    RedPipeItem *item = item_pos->data;
+
+    g_queue_delete_link(&rcc->priv->pipe, item_pos);
+    red_pipe_item_unref(item);
+}
+
 /* client mutex should be locked before this call */
 gboolean red_channel_client_set_migration_seamless(RedChannelClient *rcc)
 {
diff --git a/server/red-channel-client.h b/server/red-channel-client.h
index e77936d..b2386d3 100644
--- a/server/red-channel-client.h
+++ b/server/red-channel-client.h
@@ -105,8 +105,10 @@ void red_channel_client_start_connectivity_monitoring(RedChannelClient *rcc, uin
 void red_channel_client_pipe_add_push(RedChannelClient *rcc, RedPipeItem *item);
 void red_channel_client_pipe_add(RedChannelClient *rcc, RedPipeItem *item);
 void red_channel_client_pipe_add_after(RedChannelClient *rcc, RedPipeItem *item, RedPipeItem *pos);
+void red_channel_client_pipe_add_after_pos(RedChannelClient *rcc, RedPipeItem *item, GList *pos);
 int red_channel_client_pipe_item_is_linked(RedChannelClient *rcc, RedPipeItem *item);
 void red_channel_client_pipe_remove_and_release(RedChannelClient *rcc, RedPipeItem *item);
+void red_channel_client_pipe_remove_and_release_pos(RedChannelClient *rcc, GList *item_pos);
 void red_channel_client_pipe_add_tail(RedChannelClient *rcc, RedPipeItem *item);
 void red_channel_client_pipe_add_tail_and_push(RedChannelClient *rcc, RedPipeItem *item);
 /* for types that use this routine -> the pipe item should be freed */
@@ -150,7 +152,7 @@ void red_channel_client_set_header_sub_list(RedChannelClient *rcc, uint32_t sub_
  */
 
 int red_channel_client_wait_pipe_item_sent(RedChannelClient *rcc,
-                                           RedPipeItem *item,
+                                           GList *item_pos,
                                            int64_t timeout);
 int red_channel_client_wait_outgoing_item(RedChannelClient *rcc,
                                           int64_t timeout);
-- 
2.7.4



More information about the Spice-devel mailing list