[geary/wip/713150-conversations] Performance improvements to search folder
- From: Jim Nelson <jnelson src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/713150-conversations] Performance improvements to search folder
- Date: Tue, 10 Mar 2015 22:19:50 +0000 (UTC)
commit 253d4981bfc86672daf89455e1578d8ab0e60cd0
Author: Jim Nelson <jim yorba org>
Date: Tue Mar 10 15:19:36 2015 -0700
Performance improvements to search folder
.../search/imap-db-search-email-identifier.vala | 16 -----
.../imap-db/search/imap-db-search-folder.vala | 68 ++++++++++++-------
2 files changed, 43 insertions(+), 41 deletions(-)
---
diff --git a/src/engine/imap-db/search/imap-db-search-email-identifier.vala
b/src/engine/imap-db/search/imap-db-search-email-identifier.vala
index 6df1bef..cca4265 100644
--- a/src/engine/imap-db/search/imap-db-search-email-identifier.vala
+++ b/src/engine/imap-db/search/imap-db-search-email-identifier.vala
@@ -18,22 +18,6 @@ private class Geary.ImapDB.SearchEmailIdentifier : ImapDB.EmailIdentifier,
return b.compare_to(a);
}
- public static Gee.ArrayList<SearchEmailIdentifier> array_list_from_results(
- Gee.Collection<Geary.EmailIdentifier>? results) {
- Gee.ArrayList<SearchEmailIdentifier> r = new Gee.ArrayList<SearchEmailIdentifier>();
-
- if (results != null) {
- foreach (Geary.EmailIdentifier id in results) {
- SearchEmailIdentifier? search_id = id as SearchEmailIdentifier;
-
- assert(search_id != null);
- r.add(search_id);
- }
- }
-
- return r;
- }
-
// Searches for a generic EmailIdentifier in a collection of SearchEmailIdentifiers.
public static SearchEmailIdentifier? collection_get_email_identifier(
Gee.Collection<SearchEmailIdentifier> collection, Geary.EmailIdentifier id) {
diff --git a/src/engine/imap-db/search/imap-db-search-folder.vala
b/src/engine/imap-db/search/imap-db-search-folder.vala
index f86482e..cd6863a 100644
--- a/src/engine/imap-db/search/imap-db-search-folder.vala
+++ b/src/engine/imap-db/search/imap-db-search-folder.vala
@@ -6,7 +6,7 @@
private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSupport.Remove {
// Max number of emails that can ever be in the folder.
- public const int MAX_RESULT_EMAILS = 1000;
+ public const int MAX_RESULT_EMAILS = 5000;
private const Geary.SpecialFolderType[] exclude_types = {
Geary.SpecialFolderType.SPAM,
@@ -17,6 +17,8 @@ private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSuppor
private Gee.HashSet<Geary.FolderPath?> exclude_folders = new Gee.HashSet<Geary.FolderPath?>();
private Gee.TreeSet<ImapDB.SearchEmailIdentifier> search_results;
+ private Gee.HashMap<int64?, ImapDB.SearchEmailIdentifier> message_id_to_search_result =
+ new Gee.HashMap<int64?, ImapDB.SearchEmailIdentifier>(Collection.int64_hash_func,
Collection.int64_equal_func);
private Geary.Nonblocking.Mutex result_mutex = new Geary.Nonblocking.Mutex();
public SearchFolder(Geary.Account account) {
@@ -71,14 +73,11 @@ private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSuppor
// Translate all ImapDB.EmailIdentifiers to the SearchEmailIdentifiers in the search results
// ... must do this in order to get the SearchEmailIdentifier's ordering, which is different
// than other ImapDB.EmailIdentifiers
- //
- // TODO: A dictionary of message_id => SearchEmailIdentifier would be useful here
Gee.TreeSet<ImapDB.SearchEmailIdentifier> in_folder = new
Gee.TreeSet<ImapDB.SearchEmailIdentifier>();
foreach (ImapDB.EmailIdentifier db_id in db_ids) {
- foreach (ImapDB.SearchEmailIdentifier search_id in search_results) {
- if (search_id.message_id == db_id.message_id)
- in_folder.add(search_id);
- }
+ ImapDB.SearchEmailIdentifier? search_id = message_id_to_search_result[db_id.message_id];
+ if (search_id != null)
+ in_folder.add(search_id);
}
if (in_folder.size == 0)
@@ -121,18 +120,26 @@ private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSuppor
private async void handle_removed_email_async(Geary.SearchQuery query, Geary.Folder folder,
Gee.Collection<Geary.EmailIdentifier> ids, Cancellable? cancellable) throws Error {
+ // build the list outside of the mutex, which is only required where there's a yield
+ Gee.ArrayList<ImapDB.SearchEmailIdentifier> relevant_ids = new
Gee.ArrayList<ImapDB.SearchEmailIdentifier>();
+ foreach (Geary.EmailIdentifier id in ids) {
+ ImapDB.EmailIdentifier? db_id = id as ImapDB.EmailIdentifier;
+ if (db_id == null)
+ continue;
+
+ ImapDB.SearchEmailIdentifier? search_id = message_id_to_search_result[db_id.message_id];
+ if (search_id != null)
+ relevant_ids.add(search_id);
+ }
+
+ if (relevant_ids.size == 0)
+ return;
+
int result_mutex_token = yield result_mutex.claim_async();
Error? error = null;
try {
- Gee.ArrayList<ImapDB.SearchEmailIdentifier> relevant_ids
- = Geary.traverse<Geary.EmailIdentifier>(ids)
- .map_nonnull<ImapDB.SearchEmailIdentifier>(
- id => ImapDB.SearchEmailIdentifier.collection_get_email_identifier(search_results, id))
- .to_array_list();
-
- if (relevant_ids.size > 0)
- yield do_search_async(query, null, relevant_ids, cancellable);
+ yield do_search_async(query, null, relevant_ids, cancellable);
} catch(Error e) {
error = e;
}
@@ -227,29 +234,39 @@ private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSuppor
// smarter about only fetching the search results in list_email_async()
// etc., but this leads to some more complications when redoing the
// search.
- Gee.ArrayList<ImapDB.SearchEmailIdentifier> results
- = ImapDB.SearchEmailIdentifier.array_list_from_results(yield account.local_search_async(
- query, MAX_RESULT_EMAILS, 0, exclude_folders, add_ids ?? remove_ids, cancellable));
+ Gee.Collection<Geary.EmailIdentifier>? full_results = yield account.local_search_async(
+ query, MAX_RESULT_EMAILS, 0, exclude_folders, add_ids ?? remove_ids, cancellable);
+ if (full_results == null || full_results.size == 0)
+ return;
- Gee.List<ImapDB.SearchEmailIdentifier> added
- = Gee.List.empty<ImapDB.SearchEmailIdentifier>();
- Gee.List<ImapDB.SearchEmailIdentifier> removed
- = Gee.List.empty<ImapDB.SearchEmailIdentifier>();
+ Gee.HashSet<ImapDB.SearchEmailIdentifier> results =
Geary.traverse<Geary.EmailIdentifier>(full_results)
+ .map_nonnull<ImapDB.SearchEmailIdentifier>(id => id as ImapDB.SearchEmailIdentifier)
+ .to_hash_set();
+ Gee.List<ImapDB.SearchEmailIdentifier> added = Gee.List.empty<ImapDB.SearchEmailIdentifier>();
if (remove_ids == null) {
added = Geary.traverse<ImapDB.SearchEmailIdentifier>(results)
.filter(id => !(id in search_results))
.to_array_list();
+
+ foreach (ImapDB.SearchEmailIdentifier sid in added)
+ message_id_to_search_result[sid.message_id] = sid;
+
+ search_results.add_all(added);
}
+
+ Gee.List<ImapDB.SearchEmailIdentifier> removed = Gee.List.empty<ImapDB.SearchEmailIdentifier>();
if (add_ids == null) {
removed = Geary.traverse<ImapDB.SearchEmailIdentifier>(remove_ids ?? search_results)
.filter(id => !(id in results))
.to_array_list();
+
+ foreach (ImapDB.SearchEmailIdentifier sid in removed)
+ message_id_to_search_result.unset(sid.message_id);
+
+ search_results.remove_all(removed);
}
- search_results.remove_all(removed);
- search_results.add_all(added);
-
((ImapDB.SearchFolderProperties) properties).set_total(search_results.size);
// Note that we probably shouldn't be firing these signals from inside
@@ -420,6 +437,7 @@ private class Geary.ImapDB.SearchFolder : Geary.SearchFolder, Geary.FolderSuppor
private void clear_search_results() {
search_results = new Gee.TreeSet<ImapDB.SearchEmailIdentifier>(
ImapDB.SearchEmailIdentifier.compare_descending);
+ message_id_to_search_result.clear();
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]