[geary/wip/search-fixes: 5/10] Execute ConversationMonitor ops in batches to avoid UI stalling
- From: Michael Gratton <mjog src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [geary/wip/search-fixes: 5/10] Execute ConversationMonitor ops in batches to avoid UI stalling
- Date: Tue, 6 Aug 2019 11:24:58 +0000 (UTC)
commit ce51b74e92d0dc897007d607bf359e317caf41c9
Author: Michael Gratton <mike vee net>
Date: Mon Aug 5 18:08:21 2019 +1000
Execute ConversationMonitor ops in batches to avoid UI stalling
When search results are updated in response to a serch query changing,
there can be both very large (up to 1000, the current hard-coded limit)
email and hence converstion inserts and removals in the search folder.
This splits up these large ops that execute multiple times in batches
(currently n=20), so that the main thread has a chance to breathe while
handling the updates.
.../conversation-monitor/app-append-operation.vala | 22 +++++------
.../app-conversation-operation.vala | 43 +++++++++++++++++++++-
.../app-external-append-operation.vala | 22 ++++++-----
.../app-fill-window-operation.vala | 17 +++++++--
.../conversation-monitor/app-insert-operation.vala | 23 ++++++------
.../conversation-monitor/app-remove-operation.vala | 28 +++++++-------
6 files changed, 102 insertions(+), 53 deletions(-)
---
diff --git a/src/engine/app/conversation-monitor/app-append-operation.vala
b/src/engine/app/conversation-monitor/app-append-operation.vala
index 8507da24..f8960a00 100644
--- a/src/engine/app/conversation-monitor/app-append-operation.vala
+++ b/src/engine/app/conversation-monitor/app-append-operation.vala
@@ -1,27 +1,25 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
+ * Copyright 2019 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
-private class Geary.App.AppendOperation : ConversationOperation {
-
-
- private Gee.Collection<Geary.EmailIdentifier> appended_ids;
+private class Geary.App.AppendOperation : BatchOperation<EmailIdentifier> {
public AppendOperation(ConversationMonitor monitor,
- Gee.Collection<Geary.EmailIdentifier> appended_ids) {
- base(monitor);
- this.appended_ids = appended_ids;
+ Gee.Collection<EmailIdentifier> appended_ids) {
+ base(monitor, appended_ids);
}
- public override async void execute_async() throws Error {
- debug("%d message(s) appended to %s, fetching to add to conversations...",
- this.appended_ids.size, this.monitor.base_folder.to_string());
+ public override async void execute_batch(Gee.Collection<EmailIdentifier> batch)
+ throws GLib.Error {
+ debug("Appending %d message(s) to %s",
+ batch.size, this.monitor.base_folder.to_string());
- yield this.monitor.load_by_sparse_id(this.appended_ids);
+ yield this.monitor.load_by_sparse_id(batch);
}
}
diff --git a/src/engine/app/conversation-monitor/app-conversation-operation.vala
b/src/engine/app/conversation-monitor/app-conversation-operation.vala
index b0948a6f..118b3484 100644
--- a/src/engine/app/conversation-monitor/app-conversation-operation.vala
+++ b/src/engine/app/conversation-monitor/app-conversation-operation.vala
@@ -1,9 +1,9 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
@@ -32,3 +32,42 @@ internal abstract class Geary.App.ConversationOperation : BaseObject {
public abstract async void execute_async() throws Error;
}
+
+/**
+ * An operation that executes on a collection in batches.
+ */
+internal abstract class Geary.App.BatchOperation<T> : ConversationOperation {
+
+
+ private const int BATCH_MAX_N = 20;
+
+
+ private Gee.Collection<T> full;
+
+
+ protected BatchOperation(ConversationMonitor? monitor,
+ Gee.Collection<T> full) {
+ base(monitor, true);
+ this.full = full;
+ }
+
+ public override async void execute_async() throws GLib.Error {
+ Gee.Collection<T>? batch = new Gee.LinkedList<T>();
+ foreach (T element in this.full) {
+ batch.add(element);
+
+ if (batch.size == BATCH_MAX_N) {
+ yield execute_batch(batch);
+ batch = new Gee.LinkedList<T>();
+ }
+ }
+
+ if (!batch.is_empty) {
+ yield execute_batch(batch);
+ }
+ }
+
+ public abstract async void execute_batch(Gee.Collection<T> batch)
+ throws GLib.Error;
+
+}
diff --git a/src/engine/app/conversation-monitor/app-external-append-operation.vala
b/src/engine/app/conversation-monitor/app-external-append-operation.vala
index ee9acaa2..530122e7 100644
--- a/src/engine/app/conversation-monitor/app-external-append-operation.vala
+++ b/src/engine/app/conversation-monitor/app-external-append-operation.vala
@@ -1,32 +1,34 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
+ * Copyright 2019 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
-private class Geary.App.ExternalAppendOperation : ConversationOperation {
+private class Geary.App.ExternalAppendOperation : BatchOperation<EmailIdentifier> {
+
private Geary.Folder folder;
- private Gee.Collection<Geary.EmailIdentifier> appended_ids;
+
public ExternalAppendOperation(ConversationMonitor monitor,
Geary.Folder folder,
- Gee.Collection<Geary.EmailIdentifier> appended_ids) {
- base(monitor);
+ Gee.Collection<EmailIdentifier> appended_ids) {
+ base(monitor, appended_ids);
this.folder = folder;
- this.appended_ids = appended_ids;
}
- public override async void execute_async() throws Error {
+ public override async void execute_batch(Gee.Collection<EmailIdentifier> batch)
+ throws GLib.Error {
if (!this.monitor.get_search_folder_blacklist().contains(folder.path) &&
!this.monitor.conversations.is_empty) {
- debug("%d out of folder message(s) appended to %s, fetching to add to conversations...",
- this.appended_ids.size,
+ debug("Appending %d out of folder message(s) to %s",
+ batch.size,
this.folder.to_string());
yield this.monitor.external_load_by_sparse_id(
- this.folder, this.appended_ids, Geary.Folder.ListFlags.NONE
+ this.folder, batch, Geary.Folder.ListFlags.NONE
);
}
}
diff --git a/src/engine/app/conversation-monitor/app-fill-window-operation.vala
b/src/engine/app/conversation-monitor/app-fill-window-operation.vala
index 40231bc9..0138ed31 100644
--- a/src/engine/app/conversation-monitor/app-fill-window-operation.vala
+++ b/src/engine/app/conversation-monitor/app-fill-window-operation.vala
@@ -1,9 +1,9 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
- * Copyright 2018 Michael Gratton <mike vee net>
+ * Copyright 2018-2019 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
private class Geary.App.FillWindowOperation : ConversationOperation {
@@ -38,14 +38,23 @@ private class Geary.App.FillWindowOperation : ConversationOperation {
}
debug(
- "Filling %d messages in %s...",
- num_to_load, this.monitor.base_folder.to_string()
+ "Filling %d more messages in %s...",
+ num_to_load,
+ this.monitor.base_folder.to_string()
);
int loaded = yield this.monitor.load_by_id_async(
this.monitor.window_lowest, num_to_load
);
+ debug(
+ "Filled %d of %d, window: %d, total: %d",
+ loaded, num_to_load,
+ this.monitor.conversations.size,
+ this.monitor.base_folder.properties.email_total
+ );
+
+
// Check to see if we need any more, but only if there might
// be some more to load either locally or from the remote. If
// we loaded the full amount, there might be some more
diff --git a/src/engine/app/conversation-monitor/app-insert-operation.vala
b/src/engine/app/conversation-monitor/app-insert-operation.vala
index 14f63ebb..64475a86 100644
--- a/src/engine/app/conversation-monitor/app-insert-operation.vala
+++ b/src/engine/app/conversation-monitor/app-insert-operation.vala
@@ -1,42 +1,41 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
+ * Copyright 2019 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
/**
* Handles an insertion of messages from a monitor's base folder.
*/
-private class Geary.App.InsertOperation : ConversationOperation {
+private class Geary.App.InsertOperation : BatchOperation<EmailIdentifier> {
- private Gee.Collection<EmailIdentifier> inserted_ids;
-
public InsertOperation(ConversationMonitor monitor,
Gee.Collection<EmailIdentifier> inserted_ids) {
- base(monitor);
- this.inserted_ids = inserted_ids;
+ base(monitor, inserted_ids);
}
- public override async void execute_async() throws Error {
+ public override async void execute_batch(Gee.Collection<EmailIdentifier> batch)
+ throws GLib.Error {
Geary.EmailIdentifier? lowest = this.monitor.window_lowest;
Gee.Collection<EmailIdentifier>? to_insert = null;
if (lowest != null) {
to_insert = new Gee.LinkedList<EmailIdentifier>();
- foreach (EmailIdentifier inserted in this.inserted_ids) {
+ foreach (EmailIdentifier inserted in batch) {
if (lowest.natural_sort_comparator(inserted) < 0) {
to_insert.add(inserted);
}
}
} else {
- to_insert = this.inserted_ids;
+ to_insert = batch;
}
- debug("Inserting %d messages in %s after %d inserted...",
+ debug("Inserting %d of %d messages into %s",
to_insert.size,
- this.monitor.base_folder.to_string(),
- this.inserted_ids.size);
+ batch.size,
+ this.monitor.base_folder.to_string());
yield this.monitor.load_by_sparse_id(to_insert);
}
}
diff --git a/src/engine/app/conversation-monitor/app-remove-operation.vala
b/src/engine/app/conversation-monitor/app-remove-operation.vala
index 33cbc6d8..8105d959 100644
--- a/src/engine/app/conversation-monitor/app-remove-operation.vala
+++ b/src/engine/app/conversation-monitor/app-remove-operation.vala
@@ -1,26 +1,28 @@
/*
* Copyright 2016 Software Freedom Conservancy Inc.
+ * Copyright 2019 Michael Gratton <mike vee net>
*
* This software is licensed under the GNU Lesser General Public License
- * (version 2.1 or later). See the COPYING file in this distribution.
+ * (version 2.1 or later). See the COPYING file in this distribution.
*/
-private class Geary.App.RemoveOperation : ConversationOperation {
+private class Geary.App.RemoveOperation : BatchOperation<EmailIdentifier> {
+
+
+ private Folder source_folder;
- private Geary.Folder source_folder;
- private Gee.Collection<Geary.EmailIdentifier> removed_ids;
public RemoveOperation(ConversationMonitor monitor,
- Geary.Folder source_folder,
- Gee.Collection<Geary.EmailIdentifier> removed_ids) {
- base(monitor);
+ Folder source_folder,
+ Gee.Collection<EmailIdentifier> removed_ids) {
+ base(monitor, removed_ids);
this.source_folder = source_folder;
- this.removed_ids = removed_ids;
}
- public override async void execute_async() throws Error {
- debug("%d messages(s) removed from %s, trimming/removing conversations...",
- this.removed_ids.size, this.source_folder.to_string()
+ public override async void execute_batch(Gee.Collection<EmailIdentifier> batch)
+ throws GLib.Error {
+ debug("Removing %d messages(s) from %s",
+ batch.size, this.source_folder.to_string()
);
Gee.Set<Conversation> removed = new Gee.HashSet<Conversation>();
@@ -28,7 +30,7 @@ private class Geary.App.RemoveOperation : ConversationOperation {
new Gee.HashMultiMap<Conversation, Geary.Email>();
this.monitor.conversations.remove_all_emails_by_identifier(
source_folder.path,
- removed_ids,
+ batch,
removed,
trimmed
);
@@ -38,7 +40,7 @@ private class Geary.App.RemoveOperation : ConversationOperation {
this.monitor.removed(
removed,
trimmed,
- (this.source_folder == this.monitor.base_folder) ? this.removed_ids : null
+ (this.source_folder == this.monitor.base_folder) ? batch : null
);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]