[PATCH 5/5] Add the tag list to the unified message metadata pass.

Austin Clements amdragon at MIT.EDU
Thu Dec 9 12:59:56 PST 2010


Now each caller of notmuch_message_get_tags only gets a new iterator,
instead of a whole new list.  In principle this could cause problems
with iterating while modifying tags, but through the magic of talloc
references, we keep the old tag list alive even after the cache in the
message object is invalidated.

This reduces my index search from the 3.102 seconds before the unified
metadata pass to 1.811 seconds (1.7X faster).  Combined with the
thread search optimization in b3caef1f0659dac8183441357c8fee500a940889,
that makes this query 2.5X faster than when I started.
---
 lib/message.cc |   32 ++++++++++++++++++++++++--------
 1 files changed, 24 insertions(+), 8 deletions(-)

diff --git a/lib/message.cc b/lib/message.cc
index adb205f..cc75a71 100644
--- a/lib/message.cc
+++ b/lib/message.cc
@@ -32,6 +32,7 @@ struct _notmuch_message {
     char *message_id;
     char *thread_id;
     char *in_reply_to;
+    notmuch_string_list_t *tag_list;
     notmuch_string_list_t *filename_term_list;
     notmuch_string_list_t *filename_list;
     char *author;
@@ -102,6 +103,7 @@ _notmuch_message_create_for_document (const void *talloc_owner,
     message->message_id = NULL;
     message->thread_id = NULL;
     message->in_reply_to = NULL;
+    message->tag_list = NULL;
     message->filename_term_list = NULL;
     message->filename_list = NULL;
     message->message_file = NULL;
@@ -293,6 +295,7 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message)
 {
     Xapian::TermIterator i, end;
     const char *thread_prefix = _find_prefix ("thread"),
+	*tag_prefix = _find_prefix ("tag"),
 	*id_prefix = _find_prefix ("id"),
 	*filename_prefix = _find_prefix ("file-direntry"),
 	*replyto_prefix = _find_prefix ("replyto");
@@ -311,6 +314,13 @@ _notmuch_message_ensure_metadata (notmuch_message_t *message)
 	message->thread_id =
 	    _notmuch_message_get_term (message, i, end, thread_prefix);
 
+    /* Get tags */
+    if (!message->tag_list) {
+	message->tag_list =
+	    _notmuch_get_terms_with_prefix (message, i, end, tag_prefix);
+	_notmuch_string_list_sort (message->tag_list);
+    }
+
     /* Get id */
     assert (strcmp (thread_prefix, id_prefix) < 0);
     if (!message->message_id)
@@ -345,6 +355,11 @@ _notmuch_message_invalidate_metadata (notmuch_message_t *message,
 	message->thread_id = NULL;
     }
 
+    if (strcmp ("tag", prefix_name) == 0) {
+	talloc_unlink (message, message->tag_list);
+	message->tag_list = NULL;
+    }
+
     if (strcmp ("file-direntry", prefix_name) == 0) {
 	talloc_free (message->filename_term_list);
 	talloc_free (message->filename_list);
@@ -645,14 +660,14 @@ notmuch_message_get_date (notmuch_message_t *message)
 notmuch_tags_t *
 notmuch_message_get_tags (notmuch_message_t *message)
 {
-    Xapian::TermIterator i, end;
-    notmuch_string_list_t *tags;
-    i = message->doc.termlist_begin();
-    end = message->doc.termlist_end();
-    tags = _notmuch_get_terms_with_prefix (message, i, end,
-					   _find_prefix ("tag"));
-    _notmuch_string_list_sort (tags);
-    return _notmuch_tags_create (message, tags, TRUE);
+    if (!message->tag_list)
+	_notmuch_message_ensure_metadata (message);
+
+    /* We tell the iterator to add a talloc reference to the
+     * underlying list, rather than stealing it.  As a result, it's
+     * possible to modify the message tags while iterating because
+     * the iterator will keep the current list alive. */
+    return _notmuch_tags_create (message, message->tag_list, FALSE);
 }
 
 const char *
@@ -1210,6 +1225,7 @@ notmuch_message_remove_all_tags (notmuch_message_t *message)
     if (! message->frozen)
 	_notmuch_message_sync (message);
 
+    talloc_free (tags);
     return NOTMUCH_STATUS_SUCCESS;
 }
 
-- 
1.7.2.3



More information about the notmuch mailing list