]> git.proxmox.com Git - mirror_qemu.git/commitdiff
memory: optimize memory_region_sync_dirty_bitmap
authorPaolo Bonzini <pbonzini@redhat.com>
Fri, 23 Sep 2016 09:08:54 +0000 (11:08 +0200)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 24 Oct 2016 13:27:19 +0000 (15:27 +0200)
Avoid walking the FlatView of all address spaces.  Most of the
address spaces will have no log_sync callback on their listeners.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
memory.c

index c857722f8640f78e77661dba2cb1f0f5301a987b..edbc7012b68492cea52a92543ef6fd1aa0d07266 100644 (file)
--- a/memory.c
+++ b/memory.c
@@ -1642,14 +1642,26 @@ bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
 
 void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
 {
+    MemoryListener *listener;
     AddressSpace *as;
+    FlatView *view;
     FlatRange *fr;
 
-    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
-        FlatView *view = address_space_get_flatview(as);
+    /* If the same address space has multiple log_sync listeners, we
+     * visit that address space's FlatView multiple times.  But because
+     * log_sync listeners are rare, it's still cheaper than walking each
+     * address space once.
+     */
+    QTAILQ_FOREACH(listener, &memory_listeners, link) {
+        if (!listener->log_sync) {
+            continue;
+        }
+        as = listener->address_space;
+        view = address_space_get_flatview(as);
         FOR_EACH_FLAT_RANGE(fr, view) {
             if (fr->mr == mr) {
-                MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
+                MemoryRegionSection mrs = section_from_flat_range(fr, as);
+                listener->log_sync(listener, &mrs);
             }
         }
         flatview_unref(view);