mirror of https://github.com/djcb/mu.git
* lib/mu-container: remove some O(n*n) behavior from threading
mu_container_append_siblings was showing up high in profiles as it has to walk chains of next->next->next->... pointers to find the last one. we now cache the last link in the chain. for listing ~ 23K messages, this saves about 20%.
This commit is contained in:
parent
7fe594fb2a
commit
e483291a1d
|
@ -80,15 +80,6 @@ set_parent (MuContainer *c, MuContainer *parent)
|
|||
}
|
||||
}
|
||||
|
||||
static MuContainer*
|
||||
find_last (MuContainer *c)
|
||||
{
|
||||
while (c && c->next)
|
||||
c = c->next;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
G_GNUC_UNUSED static gboolean
|
||||
check_dup (MuContainer *c, GHashTable *hash)
|
||||
|
@ -131,7 +122,21 @@ mu_container_append_siblings (MuContainer *c, MuContainer *sibling)
|
|||
/* assert_no_duplicates (c); */
|
||||
|
||||
set_parent (sibling, c->parent);
|
||||
(find_last(c))->next = sibling;
|
||||
|
||||
/* find the last sibling and append; first we try our cache
|
||||
* 'last', otherwise we need to walk the chain. We use a
|
||||
* cached last as to avoid walking the chain (which is
|
||||
* O(n*n)) */
|
||||
if (c->last)
|
||||
c->last->next = sibling;
|
||||
else {
|
||||
/* no 'last' cached, so walk the chain */
|
||||
MuContainer *c2;
|
||||
for (c2 = c; c2 && c2->next; c2 = c2->next);
|
||||
c2->next = sibling;
|
||||
}
|
||||
/* update the cached last */
|
||||
c->last = sibling->last ? sibling->last : sibling;
|
||||
|
||||
/* assert_no_duplicates (c); */
|
||||
|
||||
|
@ -158,6 +163,13 @@ mu_container_remove_sibling (MuContainer *c, MuContainer *sibling)
|
|||
prev = cur;
|
||||
}
|
||||
|
||||
/* unset the cached last; it's not valid anymore
|
||||
*
|
||||
* TODO: we could actually do a better job updating last
|
||||
* rather than invalidating it. */
|
||||
if (c)
|
||||
c->last = NULL;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
|
@ -201,7 +213,8 @@ typedef void (*MuContainerPathForeachFunc) (MuContainer*, gpointer, Path*);
|
|||
|
||||
static void
|
||||
mu_container_path_foreach_real (MuContainer *c, guint level, Path *path,
|
||||
MuContainerPathForeachFunc func, gpointer user_data)
|
||||
MuContainerPathForeachFunc func,
|
||||
gpointer user_data)
|
||||
{
|
||||
if (!c)
|
||||
return;
|
||||
|
@ -210,7 +223,8 @@ mu_container_path_foreach_real (MuContainer *c, guint level, Path *path,
|
|||
func (c, user_data, path);
|
||||
|
||||
/* children */
|
||||
mu_container_path_foreach_real (c->child, level + 1, path, func, user_data);
|
||||
mu_container_path_foreach_real (c->child, level + 1, path,
|
||||
func, user_data);
|
||||
|
||||
/* siblings */
|
||||
mu_container_path_foreach_real (c->next, level, path, func, user_data);
|
||||
|
|
|
@ -29,8 +29,7 @@ enum _MuContainerFlag {
|
|||
MU_CONTAINER_FLAG_SPLICE = 1 << 1,
|
||||
MU_CONTAINER_FLAG_DUP = 1 << 2
|
||||
};
|
||||
|
||||
typedef guint8 MuContainerFlag;
|
||||
typedef enum _MuContainerFlag MuContainerFlag;
|
||||
|
||||
/*
|
||||
* MuContainer data structure, as seen in JWZs document:
|
||||
|
@ -38,10 +37,21 @@ typedef guint8 MuContainerFlag;
|
|||
*/
|
||||
struct _MuContainer {
|
||||
struct _MuContainer *parent, *child, *next;
|
||||
MuContainerFlag flags;
|
||||
MuMsg *msg;
|
||||
guint docid;
|
||||
const char* msgid;
|
||||
|
||||
/* note: we cache the last of the string of next->next->...
|
||||
* `mu_container_append_siblings' shows up high in the
|
||||
* profiles since it needs to walk to the end, and this give
|
||||
* O(n*n) behavior.
|
||||
* */
|
||||
struct _MuContainer *last;
|
||||
|
||||
|
||||
MuMsg *msg;
|
||||
const char *msgid;
|
||||
|
||||
unsigned docid;
|
||||
MuContainerFlag flags;
|
||||
|
||||
};
|
||||
typedef struct _MuContainer MuContainer;
|
||||
|
||||
|
@ -177,7 +187,8 @@ typedef int (*MuContainerCmpFunc) (MuContainer *c1, MuContainer *c2,
|
|||
*
|
||||
* @return a sorted container
|
||||
*/
|
||||
MuContainer* mu_container_sort (MuContainer *c, MuMsgFieldId mfid, gboolean revert,
|
||||
MuContainer* mu_container_sort (MuContainer *c, MuMsgFieldId mfid,
|
||||
gboolean revert,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue