[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