From: Jia Jia <physicalmtea@gmail.com>
To: sgarzare@redhat.com
Cc: stefanha@redhat.com, mst@redhat.com, jasowang@redhat.com,
eperezma@redhat.com, kvm@vger.kernel.org,
virtualization@lists.linux.dev, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH v4] vhost/vsock: batch RX used-ring updates
Date: Sun, 6 Sep 2026 09:36:59 +0800 [thread overview]
Message-ID: <20260906013659.517889-1-physicalmtea@gmail.com> (raw)
vhost_transport_do_send_pkt() calls vhost_add_used() for every Guest RX
buffer even though it delays the Guest signal until the worker finishes.
Each call publishes one used entry and updates the used index separately.
Collect the completed buffer heads in the arrays already allocated for the
virtqueue and publish them with vhost_add_used_n(). Bound the batch by the
ring size and array capacity. Flush when the batch reaches its limit or
before leaving the worker.
Each used entry describes one completed RX buffer and keeps its actual used
length, so set nheads to 1 for every entry. This patch does not change
negotiated features or compress multiple buffers into one used entry.
This patch is limited to the current skb-based vhost-vsock RX path.
Performance:
The test used vsock_perf with a fresh Guest for each state and 20 paired
runs. The Guest receiver used:
vsock_perf --port PORT --buf-size 64M --vsk-size 64M --rcvlowat 1
The Host sender used:
vsock_perf --sender 3 --port PORT --bytes 1G \
--buf-size SEND_BUF --vsk-size 64M
The table reports geometric mean Guest RX throughput.
SEND_BUF baseline RX batching RX change
(Gbit/s) (Gbit/s)
256 B 0.0795724 0.0831509 +4.497%
512 B 0.1194885 0.1210297 +1.290%
4 KiB 0.7208273 0.7242053 +0.469%
64 KiB 2.1712797 2.1951941 +1.101%
As supplementary data, perf stat measured the vhost worker cycles and
instructions per GiB in 10 paired runs. The patched implementation
reduced cycles by 3.846%, 2.162%, and 4.109%, and instructions by
2.548%, 2.084%, and 4.637% for 256 B, 4 KiB, and 64 KiB, respectively.
An AF_VSOCK request-response latency test with 10 AB/BA pairs showed no
consistent RTT change: -0.102% for 256-byte messages (4/10 pairs lower) and
+3.281% for 4-KiB messages (5/10 pairs lower), using arithmetic mean RTTs.
Signed-off-by: Jia Jia <physicalmtea@gmail.com>
Acked-by: Eugenio Pérez <eperezma@redhat.com>
---
Changes in v4:
- Simplify the performance description.
- Add a brief AF_VSOCK RTT measurement.
- Keep the batch limit within the used ring and scratch arrays, without
duplicating the worker weight limit.
- Flush after adding a used entry when the batch reaches the limit, and
remove the redundant flush in the empty-queue path.
---
drivers/vhost/vsock.c | 47 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 45 insertions(+), 2 deletions(-)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index 9aaab6bb8061..7a13abe73345 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -103,12 +103,35 @@ static bool vhost_transport_has_remote_cid(struct vsock_sock *vsk, u32 cid)
return found;
}
+static bool vhost_vsock_flush_used(struct vhost_virtqueue *vq,
+ unsigned int used_count)
+{
+ if (!used_count)
+ return false;
+
+ vhost_add_used_n(vq, vq->heads, vq->nheads, used_count);
+ return true;
+}
+
+static void vhost_vsock_add_used(struct vhost_virtqueue *vq,
+ unsigned int used_count,
+ unsigned int head, unsigned int len)
+{
+ struct vring_used_elem *used = &vq->heads[used_count];
+
+ used->id = cpu_to_vhost32(vq, head);
+ used->len = cpu_to_vhost32(vq, len);
+ vq->nheads[used_count] = 1;
+}
+
static void
vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
struct vhost_virtqueue *vq)
{
struct vhost_virtqueue *tx_vq = &vsock->vqs[VSOCK_VQ_TX];
int pkts = 0, total_len = 0;
+ unsigned int used_count = 0;
+ unsigned int used_limit;
bool added = false;
bool restart_tx = false;
@@ -120,6 +143,11 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
if (!vq_meta_prefetch(vq))
goto out;
+ /* Keep the batch within the used ring and the scratch arrays. */
+ used_limit = min_t(unsigned int, vq->num, vq->dev->iov_limit);
+ if (unlikely(!used_limit))
+ goto out;
+
/* Avoid further vmexits, we're already processing the virtqueue */
vhost_disable_notify(&vsock->dev, vq);
@@ -150,9 +178,16 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
if (head == vq->num) {
virtio_vsock_skb_queue_head(&vsock->send_pkt_queue, skb);
+
+ /* Flush completed buffers before re-enabling notifications. */
+ if (vhost_vsock_flush_used(vq, used_count)) {
+ added = true;
+ used_count = 0;
+ }
+
/* We cannot finish yet if more buffers snuck in while
* re-enabling notify.
*/
if (unlikely(vhost_enable_notify(&vsock->dev, vq))) {
vhost_disable_notify(&vsock->dev, vq);
continue;
@@ -230,8 +265,13 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
*/
virtio_transport_deliver_tap_pkt(skb);
- vhost_add_used(vq, head, sizeof(*hdr) + payload_len);
- added = true;
+ vhost_vsock_add_used(vq, used_count, head,
+ sizeof(*hdr) + payload_len);
+ used_count++;
+ if (used_count == used_limit) {
+ added |= vhost_vsock_flush_used(vq, used_count);
+ used_count = 0;
+ }
VIRTIO_VSOCK_SKB_CB(skb)->offset += payload_len;
total_len += payload_len;
@@ -264,6 +304,9 @@ vhost_transport_do_send_pkt(struct vhost_vsock *vsock,
virtio_transport_consume_skb_sent(skb, true);
}
} while(likely(!vhost_exceeds_weight(vq, ++pkts, total_len)));
+
+ added |= vhost_vsock_flush_used(vq, used_count);
+
if (added)
vhost_signal(&vsock->dev, vq);
--
2.34.1
next reply other threads:[~2026-09-06 1:37 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-06 1:36 Jia Jia [this message]
2026-09-06 4:07 ` [PATCH v4] vhost/vsock: batch RX used-ring updates Michael S. Tsirkin
2026-09-07 3:05 ` Jia Jia
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=20260906013659.517889-1-physicalmtea@gmail.com \
--to=physicalmtea@gmail.com \
--cc=eperezma@redhat.com \
--cc=jasowang@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mst@redhat.com \
--cc=netdev@vger.kernel.org \
--cc=sgarzare@redhat.com \
--cc=stefanha@redhat.com \
--cc=virtualization@lists.linux.dev \
/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