diff --git a/common/dconf-changeset.c b/common/dconf-changeset.c
index 35b02be..80cd8d2 100644
--- a/common/dconf-changeset.c
+++ b/common/dconf-changeset.c
@@ -309,6 +309,20 @@ dconf_changeset_get (DConfChangeset  *changeset,
   return TRUE;
 }
 
+/**
+ * dconf_changeset_table_iter_init:
+ * @changeset: a #DConfChangeset
+ * @iter: a pointer to a #GHashTableIter
+ *
+ * Creates a hash table iterator for the table of @changeset
+ **/
+void
+dconf_changeset_table_iter_init (DConfChangeset *changeset,
+                                 GHashTableIter *iter)
+{
+  g_hash_table_iter_init (iter, changeset->table);
+}
+
 /**
  * dconf_changeset_is_similar_to:
  * @changeset: a #DConfChangeset
diff --git a/common/dconf-changeset.h b/common/dconf-changeset.h
index b0ce450..92ef9fd 100644
--- a/common/dconf-changeset.h
+++ b/common/dconf-changeset.h
@@ -47,6 +47,9 @@ gboolean                dconf_changeset_get                             (DConfCh
                                                                          const gchar              *key,
                                                                          GVariant                **value);
 
+void                    dconf_changeset_table_iter_init                 (DConfChangeset           *changeset,
+                                                                         GHashTableIter           *iter);
+
 gboolean                dconf_changeset_is_similar_to                   (DConfChangeset           *changeset,
                                                                          DConfChangeset           *other);
 
diff --git a/engine/dconf-engine.c b/engine/dconf-engine.c
index bc36e52..318eb7e 100644
--- a/engine/dconf-engine.c
+++ b/engine/dconf-engine.c
@@ -965,6 +965,60 @@ dconf_engine_prepare_change (DConfEngine     *engine,
  */
 static void dconf_engine_manage_queue (DConfEngine *engine);
 
+/**
+ * dconf_engine_changeset_has_no_effect:
+ * @engine: a #DConfEngine to check the effect of the changes on
+ * @changeset: a #DConfChangeset
+ * @read_through: a #GQueue to include pending changes from
+ *
+ * Checks if @changeset would have no effect when applied to @engine
+ * (i.e. for all changes, the new value is the same as the old value,
+ * or the same as the pending value in @read_through).
+ *
+ * Returns: %TRUE if @changeset is empty
+ **/
+gboolean
+dconf_engine_changeset_has_no_effect (DConfEngine *engine, DConfChangeset *changeset)
+{
+  if (dconf_changeset_is_empty (changeset))
+    return TRUE;
+
+  GHashTableIter iter;
+  gpointer key, new_value;
+  GVariant *current_value;
+
+  dconf_changeset_table_iter_init (changeset, &iter);
+  while (g_hash_table_iter_next (&iter, &key, &new_value))
+    {
+      GVariant *current_value = dconf_engine_read (engine,
+                                                   DCONF_READ_USER_VALUE,
+                                                   NULL,
+                                                   key);
+
+      if (current_value == NULL)
+        {
+          return FALSE;
+        }
+      else
+        {
+          if (new_value == NULL)
+            {
+              g_variant_unref (current_value);
+              return FALSE;
+            }
+          else if (!g_variant_equal (current_value, new_value))
+            {
+              g_variant_unref (current_value);
+              return FALSE;
+            }
+
+          g_variant_unref (current_value);
+        }
+    }
+
+  return TRUE;
+}
+
 static void
 dconf_engine_emit_changes (DConfEngine    *engine,
                            DConfChangeset *changeset,
@@ -1138,6 +1192,8 @@ dconf_engine_change_fast (DConfEngine     *engine,
   if (dconf_changeset_is_empty (changeset))
     return TRUE;
 
+  gboolean has_no_effect = dconf_engine_changeset_has_no_effect (engine, changeset);
+
   if (!dconf_engine_changeset_changes_only_writable_keys (engine, changeset, error))
     return FALSE;
 
@@ -1189,7 +1245,8 @@ dconf_engine_change_fast (DConfEngine     *engine,
   dconf_engine_unlock_queues (engine);
 
   /* Emit the signal after dropping the lock to avoid deadlock on re-entry. */
-  dconf_engine_emit_changes (engine, changeset, origin_tag);
+  if (!has_no_effect)
+    dconf_engine_emit_changes (engine, changeset, origin_tag);
 
   return TRUE;
 }
diff --git a/engine/dconf-engine.h b/engine/dconf-engine.h
index 2485423..6d68d6d 100644
--- a/engine/dconf-engine.h
+++ b/engine/dconf-engine.h
@@ -137,6 +137,10 @@ G_GNUC_INTERNAL
 void                    dconf_engine_unwatch_fast                       (DConfEngine             *engine,
                                                                          const gchar             *path);
 
+G_GNUC_INTERNAL
+gboolean                dconf_engine_changeset_has_no_effect            (DConfEngine              *engine,
+                                                                         DConfChangeset           *changeset);
+
 G_GNUC_INTERNAL
 gboolean                dconf_engine_change_fast                        (DConfEngine             *engine,
                                                                          DConfChangeset          *changeset,
diff --git a/tests/engine.c b/tests/engine.c
index a804b9a..04ed57f 100644
--- a/tests/engine.c
+++ b/tests/engine.c
@@ -1528,6 +1528,25 @@ test_change_sync (void)
   dconf_engine_unref (engine);
 }
 
+static void
+test_change_effect (void)
+{
+  DConfChangeset *change, *empty_change;
+  DConfEngine *engine;
+
+  engine = dconf_engine_new (SRCDIR "/profile/dos", NULL, NULL);
+  change = dconf_changeset_new_write ("/value", g_variant_new_string ("value"));
+  empty_change = dconf_changeset_new();
+  g_assert_false (dconf_engine_changeset_has_no_effect (engine, change));
+  dconf_engine_change_fast (engine, change, NULL, NULL);
+  g_assert_true (dconf_engine_changeset_has_no_effect (engine, change));
+  g_assert_true (dconf_engine_changeset_has_no_effect (engine, empty_change));
+
+  dconf_changeset_unref (change);
+  dconf_changeset_unref (empty_change);
+  dconf_engine_unref (engine);
+}
+
 static void
 send_signal (GBusType     type,
              const gchar *name,
@@ -1760,6 +1779,7 @@ main (int argc, char **argv)
   g_test_add_func ("/engine/watch/sync", test_watch_sync);
   g_test_add_func ("/engine/change/fast", test_change_fast);
   g_test_add_func ("/engine/change/sync", test_change_sync);
+  g_test_add_func ("/engine/change/effect", test_change_effect);
   g_test_add_func ("/engine/signals", test_signals);
   g_test_add_func ("/engine/sync", test_sync);
 
