[ostree] fetcher: Add a queue to limit requests sent to soup
- From: Sjoerd Simons <sjoerds src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [ostree] fetcher: Add a queue to limit requests sent to soup
- Date: Sun, 22 Sep 2013 21:42:31 +0000 (UTC)
commit 5f310868f778d3691fcd269718258a8680394a01
Author: Sjoerd Simons <sjoerd luon net>
Date: Sun Sep 15 21:25:02 2013 +0200
fetcher: Add a queue to limit requests sent to soup
On a large ostree repository pulling over http slows to a crawl. Pulling
from localhost results in:
5944 metadata, 63734 content objects fetched; 850509 KiB transferred in
1106 seconds
In other words about 800KiB/s. Some profiling shows that essentially
all of the CPU goes into libsoup doing its request bookkeeping instead
of into the actual downloading.
Adding a simple queue to limit to number of active request sent into
libsoup makes for a dramatic improvement:
5944 metadata, 63734 content objects fetched; 850509 KiB transferred
in 89 seconds
So around 9450 KiB/s.
https://bugzilla.gnome.org/show_bug.cgi?id=708126
src/libostree/ostree-fetcher.c | 64 ++++++++++++++++++++++++++++++++++++++--
1 files changed, 61 insertions(+), 3 deletions(-)
---
diff --git a/src/libostree/ostree-fetcher.c b/src/libostree/ostree-fetcher.c
index 519345f..3316dd9 100644
--- a/src/libostree/ostree-fetcher.c
+++ b/src/libostree/ostree-fetcher.c
@@ -53,6 +53,9 @@ typedef struct {
GSimpleAsyncResult *result;
} OstreeFetcherPendingURI;
+static void ostree_fetcher_pending_uri_done (OstreeFetcher *self,
+ OstreeFetcherPendingURI *pending);
+
static void
pending_uri_free (OstreeFetcherPendingURI *pending)
{
@@ -61,6 +64,9 @@ pending_uri_free (OstreeFetcherPendingURI *pending)
if (pending->refcount > 0)
return;
+ if (!pending->is_stream)
+ ostree_fetcher_pending_uri_done (pending->self, pending);
+
soup_uri_free (pending->uri);
g_clear_object (&pending->self);
g_clear_object (&pending->out_tmpfile);
@@ -86,6 +92,11 @@ struct OstreeFetcher
guint64 total_downloaded;
guint total_requests;
+
+ /* Queue for libsoup, see bgo#708591 */
+ gint outstanding;
+ GQueue pending_queue;
+ gint max_outstanding;
};
G_DEFINE_TYPE (OstreeFetcher, ostree_fetcher, G_TYPE_OBJECT)
@@ -103,6 +114,8 @@ ostree_fetcher_finalize (GObject *object)
g_hash_table_destroy (self->sending_messages);
g_hash_table_destroy (self->message_to_request);
+ g_queue_clear (&self->pending_queue);
+
G_OBJECT_CLASS (ostree_fetcher_parent_class)->finalize (object);
}
@@ -137,12 +150,17 @@ on_request_unqueued (SoupSession *session,
static void
ostree_fetcher_init (OstreeFetcher *self)
{
+ gint max_conns;
+
+ g_queue_init (&self->pending_queue);
self->session = soup_session_async_new_with_options (SOUP_SESSION_USER_AGENT, "ostree ",
SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
SOUP_SESSION_USE_THREAD_CONTEXT, TRUE,
SOUP_SESSION_ADD_FEATURE_BY_TYPE, SOUP_TYPE_REQUESTER,
NULL);
self->requester = (SoupRequester *)soup_session_get_feature (self->session, SOUP_TYPE_REQUESTER);
+ g_object_get (self->session, "max-conns-per-host", &max_conns, NULL);
+ self->max_outstanding = 3 * max_conns;
g_signal_connect (self->session, "request-started",
G_CALLBACK (on_request_started), self);
@@ -169,6 +187,47 @@ ostree_fetcher_new (GFile *tmpdir,
}
static void
+on_request_sent (GObject *object, GAsyncResult *result, gpointer user_data);
+
+static void
+ostree_fetcher_pending_uri_done (OstreeFetcher *self,
+ OstreeFetcherPendingURI *pending)
+{
+ OstreeFetcherPendingURI *p;
+
+ g_assert (!pending->is_stream);
+
+ self->outstanding--;
+ p = g_queue_pop_head (&self->pending_queue);
+ if (p != NULL)
+ {
+ self->outstanding++;
+ soup_request_send_async (p->request, p->cancellable,
+ on_request_sent, p);
+ }
+}
+
+static void
+ostree_fetcher_queue_pending_uri (OstreeFetcher *self,
+ OstreeFetcherPendingURI *pending)
+{
+ g_assert (!pending->is_stream);
+
+ if (self->outstanding >= self->max_outstanding)
+ {
+ g_queue_push_tail (&self->pending_queue, pending);
+ }
+ else
+ {
+ self->outstanding++;
+ soup_request_send_async (pending->request, pending->cancellable,
+ on_request_sent, pending);
+ }
+}
+
+
+
+static void
on_splice_complete (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -351,9 +410,8 @@ ostree_fetcher_request_uri_with_partial_async (OstreeFetcher *self,
soup_request_http_get_message ((SoupRequestHTTP*)pending->request),
pending);
}
-
- soup_request_send_async (pending->request, cancellable,
- on_request_sent, pending);
+
+ ostree_fetcher_queue_pending_uri (self, pending);
out:
if (local_error != NULL)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]