diff options
author | Niels De Graef <nielsdegraef@gmail.com> | 2022-08-17 00:14:50 +0200 |
---|---|---|
committer | Niels De Graef <nielsdegraef@gmail.com> | 2022-08-17 01:25:56 +0200 |
commit | 7a4aa6227830680ab790e2de314aa7b7e6e15da5 (patch) | |
tree | 7837f8bc43914fba2310af06b50c5caea1d39ee9 /src | |
parent | 3b343fda88a6f328f5664104c548ee5f5e3b9f44 (diff) | |
download | gnome-contacts-7a4aa6227830680ab790e2de314aa7b7e6e15da5.tar.gz |
query-filter: Optimize for SimpleQuery
Before this commit, the QueryFilter used a very naive implementation
where it would just re-filter all contacts if something change (like a
query string). This wasn't of course the most performant thing to do,
and after some investigation we found out that on each search bar
change, we were using quite some CPU.
This commit adds some optimizations by avoiding unnecessary refiltering
of contacts where possible. This shaves off quite a few percentages of
CPU usage when doing some searching in the side bar.
Diffstat (limited to 'src')
-rw-r--r-- | src/contacts-query-filter.vala | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/src/contacts-query-filter.vala b/src/contacts-query-filter.vala index c563f73..b4459c1 100644 --- a/src/contacts-query-filter.vala +++ b/src/contacts-query-filter.vala @@ -28,6 +28,10 @@ public class Contacts.QueryFilter : Gtk.Filter { public Query query { get; construct; } + // if this.query is a SimpleQuery, we can save the query string to enable + // some optimizations (see later) + private string query_string = ""; + private uint _min_strength = 0; public uint min_strength { get { return this._min_strength; } @@ -40,20 +44,56 @@ public class Contacts.QueryFilter : Gtk.Filter { } } + construct { + if (this.query is SimpleQuery) + this.query_string = ((SimpleQuery) this.query).query_string; + this.query.notify.connect (on_query_notify); + } + public QueryFilter (Query query) { Object (query: query); - - query.notify.connect (on_query_notify); } private void on_query_notify (Object object, ParamSpec pspec) { + unowned var query = (Query) object; + + // We can optimize a bit in the case of a SimpleQuery + if (query is SimpleQuery) { + // SimpleQuery notifies its locale changed on a query string update, + // even if it didn't change (and we don't support changing it either) + if (pspec.get_name () == "query-locale") + return; + + // A very common use case is that the user is typing in the search bar. + // In case they add a letter, we know the filter will be more strict (and + // vice versa) + if (pspec.get_name () == "query-string") { + var old_query_str = this.query_string; + this.query_string = ((SimpleQuery) query).query_string; + + // We shouldn't get a notify for this but in reality we do, so ignore it + if (this.query_string == old_query_str) + return; + + if (this.query_string.length > old_query_str.length && + this.query_string.index_of (old_query_str) != -1) { + this.changed (Gtk.FilterChange.MORE_STRICT); + return; + } + if (this.query_string.length < old_query_str.length && + old_query_str.index_of (this.query_string) != -1) { + this.changed (Gtk.FilterChange.LESS_STRICT); + return; + } + } + } + this.changed (Gtk.FilterChange.DIFFERENT); } public override bool match (GLib.Object? item) { unowned var individual = item as Individual; - if (individual == null) - return false; + return_val_if_fail (individual != null, false); return this.query.is_match (individual) > this.min_strength; } |