[folks] core: Connect to Persona::notify, not all its details, in Individual



commit dbd75fa4927537eb9723d523d08edb0e11b6ea82
Author: Simon McVittie <simon mcvittie collabora co uk>
Date:   Thu Mar 28 14:02:05 2013 +0000

    core: Connect to Persona::notify, not all its details, in Individual
    
    In practice, we care about basically every property anyway, and
    tests/eds/perf was spending more than 6% of its time connecting
    to these signals. Just connect to notify and demultiplex through a
    lookup table for about a 5% speed-up.
    
    In principle we could make the lookup table into a
    hash table if it proves to be worth it, but life is probably too short.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=697209

 NEWS                  |    1 +
 folks/individual.vala |  234 +++++++++++++++++++++++-------------------------
 2 files changed, 113 insertions(+), 122 deletions(-)
---
diff --git a/NEWS b/NEWS
index 03365e3..31ee873 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,7 @@ Bugs fixed:
 • Bug 705403 — Use GLib.BytesIcon instead of Edsf.MemoryIcon
 • Bug 679826 — Investigate using parallel-tests to speed up testing
 • Bug 709674 — Ignore non-phonebook-enabled modems in ofono backend
+• Bug 697209 — Individual: connect to Persona::notify less enthusiastically
 
 API changes:
 
diff --git a/folks/individual.vala b/folks/individual.vala
index aecab69..06cae99 100644
--- a/folks/individual.vala
+++ b/folks/individual.vala
@@ -996,29 +996,29 @@ public class Folks.Individual : Object,
   public signal void personas_changed (Set<Persona> added,
       Set<Persona> removed);
 
-  private void _notify_alias_cb (Object obj, ParamSpec ps)
+  private static void _notify_alias_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_alias ();
+      self._update_alias ();
     }
 
-  private void _notify_avatar_cb (Object obj, ParamSpec ps)
+  private static void _notify_avatar_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_avatar ();
+      self._update_avatar ();
     }
 
-  private void _notify_full_name_cb ()
+  private static void _notify_full_name_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_full_name ();
+      self._update_full_name ();
     }
 
-  private void _notify_structured_name_cb ()
+  private static void _notify_structured_name_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_structured_name ();
+      self._update_structured_name ();
     }
 
-  private void _notify_nickname_cb ()
+  private static void _notify_nickname_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_nickname ();
+      self._update_nickname ();
     }
 
   private void _persona_group_changed_cb (string group, bool is_member)
@@ -1026,54 +1026,54 @@ public class Folks.Individual : Object,
       this._update_groups (false);
     }
 
-  private void _notify_gender_cb ()
+  private static void _notify_gender_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_gender ();
+      self._update_gender ();
     }
 
-  private void _notify_urls_cb ()
+  private static void _notify_urls_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_urls (false);
+      self._update_urls (false);
     }
 
-  private void _notify_phone_numbers_cb ()
+  private static void _notify_phone_numbers_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_phone_numbers (false);
+      self._update_phone_numbers (false);
     }
 
-  private void _notify_postal_addresses_cb ()
+  private static void _notify_postal_addresses_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_postal_addresses (false);
+      self._update_postal_addresses (false);
     }
 
-  private void _notify_email_addresses_cb ()
+  private static void _notify_email_addresses_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_email_addresses (false);
+      self._update_email_addresses (false);
     }
 
-  private void _notify_roles_cb ()
+  private static void _notify_roles_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_roles (false);
+      self._update_roles (false);
     }
 
-  private void _notify_birthday_cb ()
+  private static void _notify_birthday_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_birthday ();
+      self._update_birthday ();
     }
 
-  private void _notify_notes_cb ()
+  private static void _notify_notes_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_notes (false);
+      self._update_notes (false);
     }
 
-  private void _notify_local_ids_cb ()
+  private static void _notify_local_ids_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_local_ids (false);
+      self._update_local_ids (false);
     }
 
-  private void _notify_location_cb ()
+  private static void _notify_location_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_location ();
+      self._update_location ();
     }
 
   /**
@@ -1101,62 +1101,121 @@ public class Folks.Individual : Object,
        * yet; react to that directly */
     }
 
-  private void _notify_presence_cb (Object obj, ParamSpec ps)
+  private static void _notify_presence_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_presence ();
+      self._update_presence ();
     }
 
-  private void _notify_im_addresses_cb (Object obj, ParamSpec ps)
+  private static void _notify_im_addresses_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_im_addresses (false);
+      self._update_im_addresses (false);
     }
 
-  private void _notify_web_service_addresses_cb (Object obj, ParamSpec ps)
+  private static void _notify_web_service_addresses_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_web_service_addresses (false);
+      self._update_web_service_addresses (false);
     }
 
-  private void _notify_is_favourite_cb (Object obj, ParamSpec ps)
+  private static void _notify_is_favourite_cb (Individual self, Persona p, ParamSpec ps)
     {
-      this._update_is_favourite ();
+      self._update_is_favourite ();
     }
 
-  private void _notify_im_interaction_count_cb (Object obj, ParamSpec ps)
+  private static void _notify_im_interaction_count_cb (Individual self, Persona p, ParamSpec ps)
     {
       /**
        * The property is pull rather than push. This function is called in
        * response to personas emitting a similar notification.
        */
-      this.notify_property ("im-interaction-count");
+      self.notify_property ("im-interaction-count");
     }
 
-  private void _notify_call_interaction_count_cb (Object obj, ParamSpec ps)
+  private static void _notify_call_interaction_count_cb (Individual self, Persona p, ParamSpec ps)
     {
       /**
        * The property is pull rather than push. This function is called in
        * response to personas emitting a similar notification.
        */
-      this.notify_property ("call-interaction-count");
+      self.notify_property ("call-interaction-count");
     }
 
-  private void _notify_last_im_interaction_datetime_cb (Object obj, ParamSpec ps)
+  private static void _notify_last_im_interaction_datetime_cb (Individual self, Persona p, ParamSpec ps)
     {
       /**
        * The property is pull rather than push. This function is called in
        * response to personas emitting a similar notification.
        */
-      this._last_im_interaction_datetime = null;
-      this.notify_property ("last-im-interaction-datetime");
+      self._last_im_interaction_datetime = null;
+      self.notify_property ("last-im-interaction-datetime");
     }
 
-  private void _notify_last_call_interaction_datetime_cb (Object obj, ParamSpec ps)
+  private static void _notify_last_call_interaction_datetime_cb (Individual self, Persona p, ParamSpec ps)
     {
       /**
        * The property is pull rather than push. This function is called in
        * response to personas emitting a similar notification.
        */
-      this._last_call_interaction_datetime = null;
-      this.notify_property ("last-call-interaction-datetime");
+      self._last_call_interaction_datetime = null;
+      self.notify_property ("last-call-interaction-datetime");
+    }
+
+  [CCode (has_target = false)]
+  private delegate void _UnboundNotifier (Individual self,
+      Persona persona, ParamSpec ps);
+
+  private struct _Notifier
+    {
+      unowned string property;
+      _UnboundNotifier notify;
+    }
+
+  /* This contains static methods that take "this" as an explicit parameter,
+   * so that we can have one big lookup table at the class level without
+   * having to mess about with delegates.
+   *
+   * All keys in this array must be unique. */
+  private static const _Notifier _notifiers[] =
+    {
+      { "alias", Individual._notify_alias_cb },
+      { "avatar", Individual._notify_avatar_cb },
+      { "presence-message", Individual._notify_presence_cb },
+      { "client-types", Individual._notify_presence_cb },
+      { "presence-type", Individual._notify_presence_cb },
+      { "im-addresses", Individual._notify_im_addresses_cb },
+      { "web-service-addresses", Individual._notify_web_service_addresses_cb },
+      { "is-favourite", Individual._notify_is_favourite_cb },
+      { "structured-name", Individual._notify_structured_name_cb },
+      { "full-name", Individual._notify_full_name_cb },
+      { "nickname", Individual._notify_nickname_cb },
+      { "gender", Individual._notify_gender_cb },
+      { "urls", Individual._notify_urls_cb },
+      { "phone-numbers", Individual._notify_phone_numbers_cb },
+      { "email-addresses", Individual._notify_email_addresses_cb },
+      { "roles", Individual._notify_roles_cb },
+      { "birthday", Individual._notify_birthday_cb },
+      { "notes", Individual._notify_notes_cb },
+      { "postal-addresses", Individual._notify_postal_addresses_cb },
+      { "local-ids", Individual._notify_local_ids_cb },
+      { "location", Individual._notify_location_cb },
+      { "im-interaction-count", Individual._notify_im_interaction_count_cb },
+      { "call-interaction-count", Individual._notify_call_interaction_count_cb },
+      { "last-im-interaction-datetime", Individual._notify_last_im_interaction_datetime_cb },
+      { "last-call-interaction-datetime", Individual._notify_last_call_interaction_datetime_cb },
+    };
+
+  private void _persona_notify_cb (Object obj, ParamSpec ps)
+    {
+      assert (obj is Persona);
+      assert (ps.name == "individual" || (obj as Persona).individual == this);
+
+      foreach (var notifier in Individual._notifiers)
+        {
+          if (ps.name == notifier.property)
+            {
+              notifier.notify (this, (!) (obj as Persona), ps);
+              break;  /* assume all entries in notifiers are unique */
+            }
+        }
     }
 
   /**
@@ -1831,47 +1890,16 @@ public class Folks.Individual : Object,
     {
       persona.individual = this;
 
-      persona.notify["alias"].connect (this._notify_alias_cb);
-      persona.notify["avatar"].connect (this._notify_avatar_cb);
-      persona.notify["presence-message"].connect (this._notify_presence_cb);
-      persona.notify["client-types"].connect (this._notify_presence_cb);
-      persona.notify["presence-type"].connect (this._notify_presence_cb);
-      persona.notify["im-addresses"].connect (this._notify_im_addresses_cb);
-      persona.notify["web-service-addresses"].connect
-              (this._notify_web_service_addresses_cb);
-      persona.notify["is-favourite"].connect (this._notify_is_favourite_cb);
-      persona.notify["structured-name"].connect (
-          this._notify_structured_name_cb);
-      persona.notify["full-name"].connect (this._notify_full_name_cb);
-      persona.notify["nickname"].connect (this._notify_nickname_cb);
-      persona.notify["gender"].connect (this._notify_gender_cb);
-      persona.notify["urls"].connect (this._notify_urls_cb);
-      persona.notify["phone-numbers"].connect (this._notify_phone_numbers_cb);
-      persona.notify["email-addresses"].connect (
-          this._notify_email_addresses_cb);
-      persona.notify["roles"].connect (this._notify_roles_cb);
-      persona.notify["birthday"].connect (this._notify_birthday_cb);
-      persona.notify["notes"].connect (this._notify_notes_cb);
-      persona.notify["postal-addresses"].connect
-          (this._notify_postal_addresses_cb);
-      persona.notify["local-ids"].connect
-          (this._notify_local_ids_cb);
-      persona.notify["location"].connect (this._notify_location_cb);
+      /* We're interested in most, if not all, signals from a persona,
+       * so avoid a significant amount of GObject signal overhead by
+       * connecting to the entire signal and demultiplexing it ourselves. */
+      persona.notify.connect (this._persona_notify_cb);
 
       if (persona is GroupDetails)
         {
           ((GroupDetails) persona).group_changed.connect (
               this._persona_group_changed_cb);
         }
-      /* Subscribe to the interactions signal for the persona */
-      var p_interaction_details = persona as InteractionDetails;
-      if (p_interaction_details != null)
-        {
-          persona.notify["im-interaction-count"].connect (this._notify_im_interaction_count_cb);
-          persona.notify["call-interaction-count"].connect (this._notify_call_interaction_count_cb);
-          persona.notify["last-im-interaction-datetime"].connect 
(this._notify_last_im_interaction_datetime_cb);
-          persona.notify["last-call-interaction-datetime"].connect 
(this._notify_last_call_interaction_datetime_cb);
-        }
     }
 
   private void _update_structured_name ()
@@ -1969,35 +1997,7 @@ public class Folks.Individual : Object,
   private void _disconnect_from_persona (Persona persona,
       Individual? replacement_individual)
     {
-      persona.notify["alias"].disconnect (this._notify_alias_cb);
-      persona.notify["avatar"].disconnect (this._notify_avatar_cb);
-      persona.notify["presence-message"].disconnect (
-          this._notify_presence_cb);
-      persona.notify["client-types"].connect (this._notify_presence_cb);
-      persona.notify["presence-type"].disconnect (this._notify_presence_cb);
-      persona.notify["im-addresses"].disconnect (
-          this._notify_im_addresses_cb);
-      persona.notify["web-service-addresses"].disconnect (
-          this._notify_web_service_addresses_cb);
-      persona.notify["is-favourite"].disconnect (
-          this._notify_is_favourite_cb);
-      persona.notify["structured-name"].disconnect (
-          this._notify_structured_name_cb);
-      persona.notify["full-name"].disconnect (this._notify_full_name_cb);
-      persona.notify["nickname"].disconnect (this._notify_nickname_cb);
-      persona.notify["gender"].disconnect (this._notify_gender_cb);
-      persona.notify["urls"].disconnect (this._notify_urls_cb);
-      persona.notify["phone-numbers"].disconnect (
-          this._notify_phone_numbers_cb);
-      persona.notify["email-addresses"].disconnect (
-          this._notify_email_addresses_cb);
-      persona.notify["roles"].disconnect (this._notify_roles_cb);
-      persona.notify["birthday"].disconnect (this._notify_birthday_cb);
-      persona.notify["notes"].disconnect (this._notify_notes_cb);
-      persona.notify["postal-addresses"].disconnect
-          (this._notify_postal_addresses_cb);
-      persona.notify["local-ids"].disconnect (this._notify_local_ids_cb);
-      persona.notify["location"].disconnect (this._notify_location_cb);
+      persona.notify.disconnect (this._persona_notify_cb);
 
       if (persona is GroupDetails)
         {
@@ -2005,16 +2005,6 @@ public class Folks.Individual : Object,
               this._persona_group_changed_cb);
         }
 
-      /* Unsubscribe from the interactions signal for the persona */
-      var p_interaction_details = persona as InteractionDetails;
-      if (p_interaction_details != null)
-        {
-          persona.notify["im-interaction-count"].disconnect (this._notify_im_interaction_count_cb);
-          persona.notify["call-interaction-count"].disconnect (this._notify_call_interaction_count_cb);
-          persona.notify["last-im-interaction-datetime"].disconnect 
(this._notify_last_im_interaction_datetime_cb);
-          persona.notify["last-call-interaction-datetime"].disconnect 
(this._notify_last_call_interaction_datetime_cb);
-        }
-
       /* Don't update the individual if the persona's been added to the new one
        * already (and thus the new individual has already changed
        * persona.individual).


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