diff options
author | Dan Winship <danw@src.gnome.org> | 2008-04-03 23:58:38 +0000 |
---|---|---|
committer | Dan Winship <danw@src.gnome.org> | 2008-04-03 23:58:38 +0000 |
commit | 0fe9af2d15c4bc8dcd3413ace0c8e3f6dbe4b487 (patch) | |
tree | 27cbcf16d72c94a20cf148930cd453c518011188 | |
parent | 4b7d4b0a47c007fbbb3478e1b1619890ed1b545f (diff) | |
download | libsoup-0fe9af2d15c4bc8dcd3413ace0c8e3f6dbe4b487.tar.gz |
Be more aggressive about closing unused persistent connections
when needed, to avoid slow load times in WebKit.
* libsoup/soup-session-async.c (run_queue): Remove the
"try_pruning" flag from here and from all the callers, and
*always* try pruning idle connections if it would help.
* libsoup/soup-session.c (soup_session_try_prune_connection):
Rather than only closing a single connection, close all idle
connections.
svn path=/trunk/; revision=1119
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | libsoup/soup-session-async.c | 47 | ||||
-rw-r--r-- | libsoup/soup-session.c | 66 |
3 files changed, 64 insertions, 62 deletions
@@ -1,3 +1,16 @@ +2008-04-03 Dan Winship <danw@gnome.org> + + Be more aggressive about closing unused persistent connections + when needed, to avoid slow load times in WebKit. + + * libsoup/soup-session-async.c (run_queue): Remove the + "try_pruning" flag from here and from all the callers, and + *always* try pruning idle connections if it would help. + + * libsoup/soup-session.c (soup_session_try_prune_connection): + Rather than only closing a single connection, close all idle + connections. + 2008-03-29 Dan Winship <danw@gnome.org> * libsoup/soup-message.h (SoupMessage): de-constify diff --git a/libsoup/soup-session-async.c b/libsoup/soup-session-async.c index 2317cecb..060b4cf3 100644 --- a/libsoup/soup-session-async.c +++ b/libsoup/soup-session-async.c @@ -23,7 +23,8 @@ * single-threaded programs. **/ -static gboolean run_queue (SoupSessionAsync *sa, gboolean try_pruning); +static gboolean run_queue (SoupSessionAsync *sa); +static void do_idle_run_queue (SoupSession *session); static void queue_message (SoupSession *session, SoupMessage *req, SoupSessionCallback callback, gpointer user_data); @@ -85,12 +86,12 @@ soup_session_async_new_with_options (const char *optname1, ...) static void -connection_closed (SoupConnection *conn, SoupSessionAsync *sa) +connection_closed (SoupConnection *conn, gpointer session) { /* Run the queue in case anyone was waiting for a connection * to be closed. */ - run_queue (sa, FALSE); + do_idle_run_queue (session); } static void @@ -109,7 +110,7 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) * queue that were waiting for the connection count * to go down, so run the queue now. */ - run_queue (sa, FALSE); + run_queue (sa); return; } @@ -125,24 +126,25 @@ got_connection (SoupConnection *conn, guint status, gpointer user_data) * idle pool and then just run the queue and see what happens. */ soup_connection_release (conn); - run_queue (sa, FALSE); + run_queue (sa); } static gboolean -run_queue (SoupSessionAsync *sa, gboolean try_pruning) +run_queue (SoupSessionAsync *sa) { SoupSession *session = SOUP_SESSION (sa); SoupMessageQueue *queue = soup_session_get_queue (session); SoupMessageQueueIter iter; SoupMessage *msg; SoupConnection *conn; - gboolean should_prune = FALSE, started_any = FALSE, is_new; + gboolean try_pruning = TRUE, should_prune = FALSE; + gboolean started_any = FALSE, is_new; /* FIXME: prefer CONNECTING messages */ try_again: for (msg = soup_message_queue_first (queue, &iter); - msg; + msg && !should_prune; msg = soup_message_queue_next (queue, &iter)) { if (!SOUP_MESSAGE_IS_STARTING (msg) || @@ -159,15 +161,12 @@ run_queue (SoupSessionAsync *sa, gboolean try_pruning) session); } else soup_connection_send_request (conn, msg); - - started_any = TRUE; } - if (try_pruning && should_prune && !started_any) { - /* We didn't manage to start any message, but there is - * at least one message in the queue that could be - * sent if we pruned an idle connection from some - * other server. + if (try_pruning && should_prune) { + /* There is at least one message in the queue that + * could be sent if we pruned an idle connection from + * some other server. */ if (soup_session_try_prune_connection (session)) { try_pruning = FALSE; @@ -181,7 +180,7 @@ run_queue (SoupSessionAsync *sa, gboolean try_pruning) static void request_restarted (SoupMessage *req, gpointer sa) { - run_queue (sa, FALSE); + run_queue (sa); } typedef struct { @@ -212,7 +211,7 @@ final_finished (SoupMessage *req, gpointer user_data) if (sa) { g_object_remove_weak_pointer (G_OBJECT (sa), (gpointer)&sa); - run_queue (sa, FALSE); + run_queue (sa); } } @@ -226,12 +225,19 @@ idle_run_queue (gpointer user_data) if (sa) { g_object_remove_weak_pointer (G_OBJECT (sa), (gpointer)&sa); - run_queue (sa, TRUE); + run_queue (sa); } return FALSE; } static void +do_idle_run_queue (SoupSession *session) +{ + soup_add_idle (soup_session_get_async_context (session), + idle_run_queue, g_object_ref (session)); +} + +static void queue_message (SoupSession *session, SoupMessage *req, SoupSessionCallback callback, gpointer user_data) { @@ -249,10 +255,7 @@ queue_message (SoupSession *session, SoupMessage *req, G_CALLBACK (final_finished), saqd); SOUP_SESSION_CLASS (soup_session_async_parent_class)->queue_message (session, req, callback, user_data); - - g_object_ref (sa); - soup_add_idle (soup_session_get_async_context (session), - idle_run_queue, sa); + do_idle_run_queue (session); } static guint diff --git a/libsoup/soup-session.c b/libsoup/soup-session.c index d200b3cd..c6899001 100644 --- a/libsoup/soup-session.c +++ b/libsoup/soup-session.c @@ -808,55 +808,41 @@ connection_started_request (SoupConnection *conn, SoupMessage *msg, msg, soup_connection_get_socket (conn)); } -static void -find_oldest_connection (gpointer key, gpointer host, gpointer data) -{ - SoupConnection *conn = key, **oldest = data; - - /* Don't prune a connection that is currently in use, or - * hasn't been used yet. - */ - if (soup_connection_is_in_use (conn) || - soup_connection_last_used (conn) == 0) - return; - - if (!*oldest || (soup_connection_last_used (conn) < - soup_connection_last_used (*oldest))) - *oldest = conn; -} - -/** - * soup_session_try_prune_connection: - * @session: a #SoupSession - * - * Finds the least-recently-used idle connection in @session and closes - * it. - * - * Return value: %TRUE if a connection was closed, %FALSE if there are - * no idle connections. - **/ gboolean soup_session_try_prune_connection (SoupSession *session) { SoupSessionPrivate *priv = SOUP_SESSION_GET_PRIVATE (session); - SoupConnection *oldest = NULL; + GPtrArray *conns; + GHashTableIter iter; + gpointer conn, host; + int i; + + conns = g_ptr_array_new (); g_mutex_lock (priv->host_lock); - g_hash_table_foreach (priv->conns, find_oldest_connection, - &oldest); - if (oldest) { - /* Ref the connection before unlocking the mutex in - * case someone else tries to prune it too. + g_hash_table_iter_init (&iter, priv->conns); + while (g_hash_table_iter_next (&iter, &conn, &host)) { + /* Don't prune a connection that is currently in use, + * or hasn't been used yet. */ - g_object_ref (oldest); - g_mutex_unlock (priv->host_lock); - soup_connection_disconnect (oldest); - g_object_unref (oldest); - return TRUE; - } else { - g_mutex_unlock (priv->host_lock); + if (!soup_connection_is_in_use (conn) && + soup_connection_last_used (conn) > 0) + g_ptr_array_add (conns, g_object_ref (conn)); + } + g_mutex_unlock (priv->host_lock); + + if (!conns->len) { + g_ptr_array_free (conns, TRUE); return FALSE; } + + for (i = 0; i < conns->len; i++) { + soup_connection_disconnect (conns->pdata[i]); + g_object_unref (conns->pdata[i]); + } + g_ptr_array_free (conns, TRUE); + + return TRUE; } static void |