[gnome-contacts/nielsdg/filters-and-sorters: 1/4] query-filter: Optimize for SimpleQuery




commit 7a4aa6227830680ab790e2de314aa7b7e6e15da5
Author: Niels De Graef <nielsdegraef gmail com>
Date:   Wed Aug 17 00:14:50 2022 +0200

    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.

 src/contacts-query-filter.vala | 48 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 44 insertions(+), 4 deletions(-)
---
diff --git a/src/contacts-query-filter.vala b/src/contacts-query-filter.vala
index c563f733..b4459c1a 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;
   }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]