summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Winship <danw@src.gnome.org>2008-04-03 23:58:38 +0000
committerDan Winship <danw@src.gnome.org>2008-04-03 23:58:38 +0000
commit0fe9af2d15c4bc8dcd3413ace0c8e3f6dbe4b487 (patch)
tree27cbcf16d72c94a20cf148930cd453c518011188
parent4b7d4b0a47c007fbbb3478e1b1619890ed1b545f (diff)
downloadlibsoup-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--ChangeLog13
-rw-r--r--libsoup/soup-session-async.c47
-rw-r--r--libsoup/soup-session.c66
3 files changed, 64 insertions, 62 deletions
diff --git a/ChangeLog b/ChangeLog
index 02f450a1..47f78e77 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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