Improve UI responsiveness + experimental [PATCH]



	Hi all,
here is a suggestion that improves UI responsiveness of Balsa A LOT (I'be 
tried that on my laptop, and it's really far better). Basically it consist 
of tracking all places in balsa sources where we hold the gdk_lock for 
long operations, and place a gdk_threads_leave(); before the long op and a 
gdk_threeads_enter() after. This can be done extensively but with care to 
avoid deadlocks. Moreover it will enable testing the MT more aggressively 
and perhaps will lead to bad locking discovery.
Good examples are all mutt calls within libbalsa funcs (these are always 
called with gdk lock held). These are generally long (like 
mx_open_mailbox,mx_check_mailbox and others) and AFAIK does not make call 
to gtk so it's safe to drop the gdk lock before calling them. The next 
step would be to improve the threading code. I guess that we should do the 
threading on an auxiliary structure (a glib tree) and the export it as a 
gtkctree (and I hope all these things will go away with 2.0 port).

Here is also a very experimental patch that does the threading without 
clearing the index the reloads it to have a "fresh" index before threading 
("fresh" means a flat index). You'll also see a lot of 
gdk_threads_leave/enter() calls. This is the more experimental part, it 
should perhaps not be enabled to begin.

This is beta work (and I'm optimist ;-), but if someone has more time than 
me nowadays I hope this could be the base for better perf of balsa 
threading.
Bye
Manu
--- balsa/src/balsa-index-threading.c	Tue Apr 16 10:00:49 2002
+++ balsa-new/src/balsa-index-threading.c	Sun Mar 31 18:18:32 2002
@@ -72,10 +72,12 @@
 			GHashTable* msg_table);
 
 static void dump(GNode *node, int indent);
+static void flatten(GtkCTree * ctree,GtkCTreeNode * parent);
 
 void
 balsa_index_threading(BalsaIndex* bindex)
 {
+    flatten(bindex->ctree,NULL);
     switch (bindex->threading_type){
     case BALSA_INDEX_THREADING_SIMPLE:
 	threading_simple(bindex);
@@ -106,15 +108,17 @@
 			    (GtkCTreeFunc)gen_container, 
 			    (gpointer)id_table);
 
+    gdk_threads_leave();
     g_hash_table_foreach(id_table, 
 			 (GHFunc)find_root_set,
 			 &root_set);
-
+    gdk_threads_enter();
     balsa_window_setup_progress(BALSA_WINDOW(bindex->window), 
                                 g_slist_length(root_set)*3);
     
     foo=root_set;
     while(foo) {
+	gdk_threads_leave();
 	g_node_traverse(foo->data,
 			/*G_PRE_ORDER,*/
 			G_POST_ORDER,
@@ -123,9 +127,10 @@
 			(GNodeTraverseFunc)prune,
 			root_set);
 	foo=g_slist_next(foo);
+	gdk_threads_enter();
         balsa_window_increment_progress(BALSA_WINDOW(bindex->window));
     }
-
+    gdk_threads_leave();
     subject_table = g_hash_table_new(g_str_hash, g_str_equal);
     g_slist_foreach(root_set, (GFunc)subject_gather, subject_table);
 
@@ -135,9 +140,12 @@
 	if(foo->data!=NULL)
 	    subject_merge(foo->data, subject_table, root_set, &save_node);
 	foo=g_slist_next(foo);
+	gdk_threads_enter();
         balsa_window_increment_progress(BALSA_WINDOW(bindex->window));
+	gdk_threads_leave();
     }
 
+    gdk_threads_enter();
     foo = root_set;
     while(foo) {
 	if(foo->data!=NULL)
@@ -164,12 +172,14 @@
 	g_slist_free(save_node);
 
     balsa_window_clear_progress(BALSA_WINDOW(bindex->window));
+    gdk_threads_leave();
     g_hash_table_destroy(subject_table);
     g_hash_table_foreach(id_table, (GHFunc)free_node, NULL);
     g_hash_table_destroy(id_table);
 
     if(root_set!=NULL)
 	g_slist_free(root_set);
+    gdk_threads_enter();
 }
 
 static void
@@ -931,4 +941,32 @@
     foo=g_hash_table_lookup(msg_table, message->message_id);
     if(foo==NULL)
 	g_hash_table_insert(msg_table, message->message_id, node);
+}
+
+/* Just puts all nodes in rows, ie break all the hierarchy down
+   to a simple list.
+   Should be called with node==NULL */
+
+static void flatten(GtkCTree * ctree,GtkCTreeNode * parent)
+{
+    GtkCTreeNode * current;
+    static depth=0;
+
+    if (!parent) {
+	for (current=gtk_ctree_node_nth(ctree,1);current;current=GTK_CTREE_ROW(current)->sibling)
+	    if (GTK_CTREE_ROW(current)->children)
+		flatten(ctree,current);
+	return;
+    }
+
+    depth++;
+    for (;current = GTK_CTREE_ROW(parent)->children;) {
+	while (GTK_CTREE_ROW(current)->children) {
+	    /* if current node has children, just move them before we can
+	       move current */
+	    flatten(ctree,current);
+	}
+	/* OK now current is a leaf, just move it to the top */
+	gtk_ctree_move(ctree,current,NULL,NULL);
+    }
 }
--- balsa/src/balsa-index.c	Tue Apr 16 10:00:49 2002
+++ balsa-new/src/balsa-index.c	Mon Apr  1 21:57:46 2002
@@ -690,7 +690,7 @@
        default setting
     */
     mbnode->threading_type = balsa_app.threading_type;
-    balsa_index_set_threading_type(bindex, mbnode->threading_type);
+    balsa_index_set_threading_type(bindex, mbnode->threading_type,TRUE);
     balsa_index_set_first_new_message(bindex);
 
     gtk_idle_add((GtkFunction) moveto_handler, bindex);
@@ -2363,7 +2401,7 @@
    recreated. This should not be necessary.
 */
 void
-balsa_index_set_threading_type(BalsaIndex * bindex, int thtype)
+balsa_index_set_threading_type(BalsaIndex * bindex, int thtype,gboolean fill)
 {
     GList *list;
     LibBalsaMailbox* mailbox = NULL;
@@ -2385,10 +2423,13 @@
     mailbox = bindex->mailbox_node->mailbox;
 
     gtk_clist_freeze(clist);
-    gtk_clist_clear(clist);
+    if (fill) {
+	g_print("Filling Index\n");
+	gtk_clist_clear(clist);
     
-    for (list = mailbox->message_list; list; list = list->next)
-	balsa_index_add(bindex, LIBBALSA_MESSAGE(list->data));
+	for (list = mailbox->message_list; list; list = list->next)
+	    balsa_index_add(bindex, LIBBALSA_MESSAGE(list->data));
+    }
 
     /* do threading */
     balsa_index_threading(bindex);
--- balsa/src/balsa-index.h	Tue Apr 16 10:00:49 2002
+++ balsa-new/src/balsa-index.h	Sat Mar 30 22:40:56 2002
@@ -80,7 +80,7 @@
                                            BalsaMailboxNode * mbnode);
     void balsa_index_refresh(BalsaIndex * bindex);
     void balsa_index_update_tree(BalsaIndex *bindex, gboolean expand);
-    void balsa_index_set_threading_type(BalsaIndex * bindex, int thtype);
+    void balsa_index_set_threading_type(BalsaIndex * bindex, int thtype,gboolean fill);
     void balsa_index_set_sort_order(BalsaIndex * bindex, int column, 
 				    GtkSortType order);
     void balsa_index_set_first_new_message(BalsaIndex * bindex);
--- balsa/src/main-window.c	Tue Apr 16 10:00:50 2002
+++ balsa-new/src/main-window.c	Sat Mar 30 15:48:17 2002
@@ -2444,7 +2458,7 @@
     BALSA_MAILBOX_NODE(gnode->data)->threading_type = 
         BALSA_INDEX_THREADING_FLAT;
     balsa_index_set_threading_type(BALSA_INDEX(index), 
-                                   BALSA_INDEX_THREADING_FLAT);
+                                   BALSA_INDEX_THREADING_FLAT,FALSE);
 }
 
 static void
@@ -2462,7 +2476,7 @@
     BALSA_MAILBOX_NODE(gnode->data)->threading_type = 
         BALSA_INDEX_THREADING_SIMPLE;
    balsa_index_set_threading_type(BALSA_INDEX(index),
-                                   BALSA_INDEX_THREADING_SIMPLE);
+                                   BALSA_INDEX_THREADING_SIMPLE,FALSE);
 }
 
 static void
@@ -2480,7 +2494,7 @@
     BALSA_MAILBOX_NODE(gnode->data)->threading_type = 
         BALSA_INDEX_THREADING_JWZ;
     balsa_index_set_threading_type(BALSA_INDEX(index),
-                                        BALSA_INDEX_THREADING_JWZ);
+                                        BALSA_INDEX_THREADING_JWZ,FALSE);
 }
 
 static void


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]