qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: "Michael S. Tsirkin" <mst@redhat.com>
To: qemu-devel@nongnu.org
Cc: Peter Maydell <peter.maydell@linaro.org>,
	Si-Wei Liu <si-wei.liu@oracle.com>,
	Joao Martins <joao.m.martins@oracle.com>,
	Jason Wang <jasowang@redhat.com>
Subject: [PULL v3 02/41] vhost: Perform memory section dirty scans once per iteration
Date: Wed, 5 Jun 2024 19:34:45 -0400	[thread overview]
Message-ID: <1775c641d54dcb24bc485ac5c871c97e85f985d8.1717630437.git.mst@redhat.com> (raw)
In-Reply-To: <cover.1717630437.git.mst@redhat.com>

From: Si-Wei Liu <si-wei.liu@oracle.com>

On setups with one or more virtio-net devices with vhost on,
dirty tracking iteration increases cost the bigger the number
amount of queues are set up e.g. on idle guests migration the
following is observed with virtio-net with vhost=on:

48 queues -> 78.11%  [.] vhost_dev_sync_region.isra.13
8 queues -> 40.50%   [.] vhost_dev_sync_region.isra.13
1 queue -> 6.89%     [.] vhost_dev_sync_region.isra.13
2 devices, 1 queue -> 18.60%  [.] vhost_dev_sync_region.isra.14

With high memory rates the symptom is lack of convergence as soon
as it has a vhost device with a sufficiently high number of queues,
the sufficient number of vhost devices.

On every migration iteration (every 100msecs) it will redundantly
query the *shared log* the number of queues configured with vhost
that exist in the guest. For the virtqueue data, this is necessary,
but not for the memory sections which are the same. So essentially
we end up scanning the dirty log too often.

To fix that, select a vhost device responsible for scanning the
log with regards to memory sections dirty tracking. It is selected
when we enable the logger (during migration) and cleared when we
disable the logger. If the vhost logger device goes away for some
reason, the logger will be re-selected from the rest of vhost
devices.

After making mem-section logger a singleton instance, constant cost
of 7%-9% (like the 1 queue report) will be seen, no matter how many
queues or how many vhost devices are configured:

48 queues -> 8.71%    [.] vhost_dev_sync_region.isra.13
2 devices, 8 queues -> 7.97%   [.] vhost_dev_sync_region.isra.14

Co-developed-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Joao Martins <joao.m.martins@oracle.com>
Signed-off-by: Si-Wei Liu <si-wei.liu@oracle.com>
Message-Id: <1710448055-11709-2-git-send-email-si-wei.liu@oracle.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
---
 include/hw/virtio/vhost.h |  1 +
 hw/virtio/vhost.c         | 67 +++++++++++++++++++++++++++++++++++----
 2 files changed, 62 insertions(+), 6 deletions(-)

diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
index 02477788df..d75faf46e9 100644
--- a/include/hw/virtio/vhost.h
+++ b/include/hw/virtio/vhost.h
@@ -129,6 +129,7 @@ struct vhost_dev {
     void *opaque;
     struct vhost_log *log;
     QLIST_ENTRY(vhost_dev) entry;
+    QLIST_ENTRY(vhost_dev) logdev_entry;
     QLIST_HEAD(, vhost_iommu) iommu_list;
     IOMMUNotifier n;
     const VhostDevConfigOps *config_ops;
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
index a1e8b79e1a..06fc71746e 100644
--- a/hw/virtio/vhost.c
+++ b/hw/virtio/vhost.c
@@ -45,6 +45,7 @@
 
 static struct vhost_log *vhost_log[VHOST_BACKEND_TYPE_MAX];
 static struct vhost_log *vhost_log_shm[VHOST_BACKEND_TYPE_MAX];
+static QLIST_HEAD(, vhost_dev) vhost_log_devs[VHOST_BACKEND_TYPE_MAX];
 
 /* Memslots used by backends that support private memslots (without an fd). */
 static unsigned int used_memslots;
@@ -149,6 +150,47 @@ bool vhost_dev_has_iommu(struct vhost_dev *dev)
     }
 }
 
+static inline bool vhost_dev_should_log(struct vhost_dev *dev)
+{
+    assert(dev->vhost_ops);
+    assert(dev->vhost_ops->backend_type > VHOST_BACKEND_TYPE_NONE);
+    assert(dev->vhost_ops->backend_type < VHOST_BACKEND_TYPE_MAX);
+
+    return dev == QLIST_FIRST(&vhost_log_devs[dev->vhost_ops->backend_type]);
+}
+
+static inline void vhost_dev_elect_mem_logger(struct vhost_dev *hdev, bool add)
+{
+    VhostBackendType backend_type;
+
+    assert(hdev->vhost_ops);
+
+    backend_type = hdev->vhost_ops->backend_type;
+    assert(backend_type > VHOST_BACKEND_TYPE_NONE);
+    assert(backend_type < VHOST_BACKEND_TYPE_MAX);
+
+    if (add && !QLIST_IS_INSERTED(hdev, logdev_entry)) {
+        if (QLIST_EMPTY(&vhost_log_devs[backend_type])) {
+            QLIST_INSERT_HEAD(&vhost_log_devs[backend_type],
+                              hdev, logdev_entry);
+        } else {
+            /*
+             * The first vhost_device in the list is selected as the shared
+             * logger to scan memory sections. Put new entry next to the head
+             * to avoid inadvertent change to the underlying logger device.
+             * This is done in order to get better cache locality and to avoid
+             * performance churn on the hot path for log scanning. Even when
+             * new devices come and go quickly, it wouldn't end up changing
+             * the active leading logger device at all.
+             */
+            QLIST_INSERT_AFTER(QLIST_FIRST(&vhost_log_devs[backend_type]),
+                               hdev, logdev_entry);
+        }
+    } else if (!add && QLIST_IS_INSERTED(hdev, logdev_entry)) {
+        QLIST_REMOVE(hdev, logdev_entry);
+    }
+}
+
 static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
                                    MemoryRegionSection *section,
                                    hwaddr first,
@@ -166,12 +208,14 @@ static int vhost_sync_dirty_bitmap(struct vhost_dev *dev,
     start_addr = MAX(first, start_addr);
     end_addr = MIN(last, end_addr);
 
-    for (i = 0; i < dev->mem->nregions; ++i) {
-        struct vhost_memory_region *reg = dev->mem->regions + i;
-        vhost_dev_sync_region(dev, section, start_addr, end_addr,
-                              reg->guest_phys_addr,
-                              range_get_last(reg->guest_phys_addr,
-                                             reg->memory_size));
+    if (vhost_dev_should_log(dev)) {
+        for (i = 0; i < dev->mem->nregions; ++i) {
+            struct vhost_memory_region *reg = dev->mem->regions + i;
+            vhost_dev_sync_region(dev, section, start_addr, end_addr,
+                                  reg->guest_phys_addr,
+                                  range_get_last(reg->guest_phys_addr,
+                                                 reg->memory_size));
+        }
     }
     for (i = 0; i < dev->nvqs; ++i) {
         struct vhost_virtqueue *vq = dev->vqs + i;
@@ -383,6 +427,7 @@ static void vhost_log_put(struct vhost_dev *dev, bool sync)
         g_free(log);
     }
 
+    vhost_dev_elect_mem_logger(dev, false);
     dev->log = NULL;
     dev->log_size = 0;
 }
@@ -998,6 +1043,15 @@ static int vhost_dev_set_log(struct vhost_dev *dev, bool enable_log)
             goto err_vq;
         }
     }
+
+    /*
+     * At log start we select our vhost_device logger that will scan the
+     * memory sections and skip for the others. This is possible because
+     * the log is shared amongst all vhost devices for a given type of
+     * backend.
+     */
+    vhost_dev_elect_mem_logger(dev, enable_log);
+
     return 0;
 err_vq:
     for (; i >= 0; --i) {
@@ -2075,6 +2129,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
             VHOST_OPS_DEBUG(r, "vhost_set_log_base failed");
             goto fail_log;
         }
+        vhost_dev_elect_mem_logger(hdev, true);
     }
     if (vrings) {
         r = vhost_dev_set_vring_enable(hdev, true);
-- 
MST



  parent reply	other threads:[~2024-06-05 23:38 UTC|newest]

Thread overview: 43+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-06-05 23:34 [PULL v3 00/41] virtio: features,fixes Michael S. Tsirkin
2024-06-05 23:34 ` [PULL v3 01/41] vhost: dirty log should be per backend type Michael S. Tsirkin
2024-06-05 23:34 ` Michael S. Tsirkin [this message]
2024-06-05 23:34 ` [PULL v3 03/41] vhost-vdpa: check vhost_vdpa_set_vring_ready() return value Michael S. Tsirkin
2024-06-05 23:34 ` [PULL v3 04/41] virtio/virtio-pci: Handle extra notification data Michael S. Tsirkin
2024-06-05 23:34 ` [PULL v3 05/41] virtio: Prevent creation of device using notification-data with ioeventfd Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 06/41] virtio-mmio: Handle extra notification data Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 07/41] virtio-ccw: " Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 08/41] vhost/vhost-user: Add VIRTIO_F_NOTIFICATION_DATA to vhost feature bits Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 09/41] Fix vhost user assertion when sending more than one fd Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 10/41] vhost-vsock: add VIRTIO_F_RING_PACKED to feature_bits Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 11/41] hw/virtio: Fix obtain the buffer id from the last descriptor Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 12/41] virtio-pci: only reset pm state during resetting Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 13/41] vhost-user-gpu: fix import of DMABUF Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 14/41] Revert "vhost-user: fix lost reconnect" Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 15/41] vhost-user: fix lost reconnect again Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 16/41] hw/cxl/mailbox: change CCI cmd set structure to be a member, not a reference Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 17/41] hw/cxl/mailbox: interface to add CCI commands to an existing CCI Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 18/41] hw/cxl/cxl-mailbox-utils: Add dc_event_log_size field to output payload of identify memory device command Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 19/41] hw/cxl/cxl-mailbox-utils: Add dynamic capacity region representative and mailbox command support Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 20/41] include/hw/cxl/cxl_device: Rename mem_size as static_mem_size for type3 memory devices Michael S. Tsirkin
2024-06-05 23:35 ` [PULL v3 21/41] hw/mem/cxl_type3: Add support to create DC regions to " Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 22/41] hw/mem/cxl-type3: Refactor ct3_build_cdat_entries_for_mr to take mr size instead of mr as argument Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 23/41] hw/mem/cxl_type3: Add host backend and address space handling for DC regions Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 24/41] hw/mem/cxl_type3: Add DC extent list representative and get DC extent list mailbox support Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 25/41] hw/cxl/cxl-mailbox-utils: Add mailbox commands to support add/release dynamic capacity response Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 26/41] hw/cxl/events: Add qmp interfaces to add/release dynamic capacity extents Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 27/41] hw/mem/cxl_type3: Add DPA range validation for accesses to DC regions Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 28/41] hw/cxl/cxl-mailbox-utils: Add superset extent release mailbox support Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 29/41] hw/mem/cxl_type3: Allow to release extent superset in QMP interface Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 30/41] hw/acpi/GI: Fix trivial parameter alignment issue Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 31/41] hw/acpi: Insert an acpi-generic-node base under acpi-generic-initiator Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 32/41] scripts/update-linux-headers: Copy setup_data.h to correct directory Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 33/41] linux-headers: update to 6.10-rc1 Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 34/41] hw/misc/pvpanic: centralize definition of supported events Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 35/41] tests/qtest/pvpanic: use centralized " Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 36/41] hw/misc/pvpanic: add support for normal shutdowns Michael S. Tsirkin
2024-06-05 23:36 ` [PULL v3 37/41] pvpanic: Emit GUEST_PVSHUTDOWN QMP event on pvpanic shutdown signal Michael S. Tsirkin
2024-06-05 23:37 ` [PULL v3 38/41] tests/qtest/pvpanic: add tests for pvshutdown event Michael S. Tsirkin
2024-06-05 23:37 ` [PULL v3 39/41] Revert "docs/specs/pvpanic: mark shutdown event as not implemented" Michael S. Tsirkin
2024-06-05 23:37 ` [PULL v3 40/41] virtio-pci: Fix the failure process in kvm_virtio_pci_vector_use_one() Michael S. Tsirkin
2024-06-05 23:37 ` [PULL v3 41/41] hw/cxl: Fix read from bogus memory Michael S. Tsirkin
2024-06-05 23:56 ` [PULL v3 00/41] virtio: features,fixes Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1775c641d54dcb24bc485ac5c871c97e85f985d8.1717630437.git.mst@redhat.com \
    --to=mst@redhat.com \
    --cc=jasowang@redhat.com \
    --cc=joao.m.martins@oracle.com \
    --cc=peter.maydell@linaro.org \
    --cc=qemu-devel@nongnu.org \
    --cc=si-wei.liu@oracle.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).