Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 0/9] TX used ring batched updating for vhost
Hi: This series implement batch updating of used ring for TX. This help to reduce the cache contention on used ring. The idea is first split datacopy path from zerocopy, and do only batching for datacopy. This is because zercopy had already supported its own batching. TX PPS was increased 25.8% and Netperf TCP does not show obvious differences. The split of datapath will also be helpful for future implementation like in order completion. Please review. Thanks Jason Wang (9): vhost_net: drop unnecessary parameter vhost_net: introduce helper to initialize tx iov iter vhost_net: introduce vhost_exceeds_weight() vhost_net: introduce get_tx_bufs() vhost_net: introduce tx_can_batch() vhost_net: split out datacopy logic vhost_net: rename vhost_rx_signal_used() to vhost_net_signal_used() vhost_net: rename VHOST_RX_BATCH to VHOST_NET_BATCH vhost_net: batch update used ring for datacopy TX drivers/vhost/net.c | 249 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 179 insertions(+), 70 deletions(-) -- 2.7.4
Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 1/9] vhost_net: drop unnecessary parameter
Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index b224036..1a8175a 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -430,7 +430,6 @@ static int vhost_net_enable_vq(struct vhost_net *n, static int vhost_net_tx_get_vq_desc(struct vhost_net *net, struct vhost_virtqueue *vq, - struct iovec iov[], unsigned int iov_size, unsigned int *out_num, unsigned int *in_num, bool *busyloop_intr) { @@ -512,9 +511,8 @@ static void handle_tx(struct vhost_net *net) vhost_zerocopy_signal_used(net, vq); busyloop_intr = false; - head = vhost_net_tx_get_vq_desc(net, vq, vq->iov, - ARRAY_SIZE(vq->iov), - &out, &in, &busyloop_intr); + head = vhost_net_tx_get_vq_desc(net, vq, &out, &in, + &busyloop_intr); /* On error, stop handling until the next kick. */ if (unlikely(head < 0)) break; -- 2.7.4
Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 2/9] vhost_net: introduce helper to initialize tx iov iter
Introduce init_iov_iter() in order to be reused by future patch. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 1a8175a..cac28fd 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -466,6 +466,18 @@ static bool vhost_exceeds_maxpend(struct vhost_net *net) min_t(unsigned int, VHOST_MAX_PEND, vq->num >> 2); } +static size_t init_iov_iter(struct vhost_virtqueue *vq, struct iov_iter *iter, + size_t hdr_size, int out) +{ + /* Skip header. TODO: support TSO. */ + size_t len = iov_length(vq->iov, out); + + iov_iter_init(iter, WRITE, vq->iov, out, len); + iov_iter_advance(iter, hdr_size); + + return iov_iter_count(iter); +} + /* Expects to be always run from workqueue - which acts as * read-size critical section for our kind of RCU. */ static void handle_tx(struct vhost_net *net) @@ -531,18 +543,14 @@ static void handle_tx(struct vhost_net *net) "out %d, int %d\n", out, in); break; } - /* Skip header. TODO: support TSO. */ - len = iov_length(vq->iov, out); - iov_iter_init(&msg.msg_iter, WRITE, vq->iov, out, len); - iov_iter_advance(&msg.msg_iter, hdr_size); + /* Sanity check */ - if (!msg_data_left(&msg)) { - vq_err(vq, "Unexpected header len for TX: " - "%zd expected %zd\n", - len, hdr_size); + len = init_iov_iter(vq, &msg.msg_iter, hdr_size, out); + if (!len) { + vq_err(vq, "Unexpected header len for TX: %zd expected %zd\n", + len, hdr_size); break; } - len = msg_data_left(&msg); zcopy_used = zcopy && len >= VHOST_GOODCOPY_LEN && !vhost_exceeds_maxpend(net) -- 2.7.4
Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 3/9] vhost_net: introduce vhost_exceeds_weight()
Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index cac28fd..b9e1674 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -478,6 +478,12 @@ static size_t init_iov_iter(struct vhost_virtqueue *vq, struct iov_iter *iter, return iov_iter_count(iter); } +static bool vhost_exceeds_weight(int pkts, int total_len) +{ + return total_len >= VHOST_NET_WEIGHT || + pkts >= VHOST_NET_PKT_WEIGHT; +} + /* Expects to be always run from workqueue - which acts as * read-size critical section for our kind of RCU. */ static void handle_tx(struct vhost_net *net) @@ -576,7 +582,6 @@ static void handle_tx(struct vhost_net *net) msg.msg_control = NULL; ubufs = NULL; } - total_len += len; if (total_len < VHOST_NET_WEIGHT && !vhost_vq_avail_empty(&net->dev, vq) && @@ -606,8 +611,7 @@ static void handle_tx(struct vhost_net *net) else vhost_zerocopy_signal_used(net, vq); vhost_net_tx_packet(net); - if (unlikely(total_len >= VHOST_NET_WEIGHT) || - unlikely(++sent_pkts >= VHOST_NET_PKT_WEIGHT)) { + if (unlikely(vhost_exceeds_weight(++sent_pkts, total_len))) { vhost_poll_queue(&vq->poll); break; } @@ -918,8 +922,7 @@ static void handle_rx(struct vhost_net *net) if (unlikely(vq_log)) vhost_log_write(vq, vq_log, log, vhost_len); total_len += vhost_len; - if (unlikely(total_len >= VHOST_NET_WEIGHT) || - unlikely(++recv_pkts >= VHOST_NET_PKT_WEIGHT)) { + if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) { vhost_poll_queue(&vq->poll); goto out; } -- 2.7.4
Factor out logic of getting tx buffer and iov iter initialization. This will be used for reducing codes duplication in the future. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 49 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 17 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index b9e1674..a014ca0 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -484,6 +484,36 @@ static bool vhost_exceeds_weight(int pkts, int total_len) pkts >= VHOST_NET_PKT_WEIGHT; } +static int get_tx_bufs(struct vhost_net *net, + struct vhost_net_virtqueue *nvq, + struct msghdr *msg, + unsigned int *out, unsigned int *in, + size_t *len, bool *busyloop_intr) +{ + struct vhost_virtqueue *vq = &nvq->vq; + int ret; + + ret = vhost_net_tx_get_vq_desc(net, vq, out, in, busyloop_intr); + if (ret < 0 || ret == vq->num) + return ret; + + if (*in) { + vq_err(vq, "Unexpected descriptor format for TX: out %d, int %d\n", + *out, *in); + return -EFAULT; + } + + /* Sanity check */ + *len = init_iov_iter(vq, &msg->msg_iter, nvq->vhost_hlen, *out); + if (*len == 0) { + vq_err(vq, "Unexpected header len for TX: %zd expected %zd\n", + *len, nvq->vhost_hlen); + return -EFAULT; + } + + return ret; +} + /* Expects to be always run from workqueue - which acts as * read-size critical section for our kind of RCU. */ static void handle_tx(struct vhost_net *net) @@ -501,7 +531,6 @@ static void handle_tx(struct vhost_net *net) }; size_t len, total_len = 0; int err; - size_t hdr_size; struct socket *sock; struct vhost_net_ubuf_ref *uninitialized_var(ubufs); bool zcopy, zcopy_used; @@ -518,7 +547,6 @@ static void handle_tx(struct vhost_net *net) vhost_disable_notify(&net->dev, vq); vhost_net_disable_vq(net, vq); - hdr_size = nvq->vhost_hlen; zcopy = nvq->ubufs; for (;;) { @@ -529,8 +557,8 @@ static void handle_tx(struct vhost_net *net) vhost_zerocopy_signal_used(net, vq); busyloop_intr = false; - head = vhost_net_tx_get_vq_desc(net, vq, &out, &in, - &busyloop_intr); + head = get_tx_bufs(net, nvq, &msg, &out, &in, &len, + &busyloop_intr); /* On error, stop handling until the next kick. */ if (unlikely(head < 0)) break; @@ -544,19 +572,6 @@ static void handle_tx(struct vhost_net *net) } break; } - if (in) { - vq_err(vq, "Unexpected descriptor format for TX: " - "out %d, int %d\n", out, in); - break; - } - - /* Sanity check */ - len = init_iov_iter(vq, &msg.msg_iter, hdr_size, out); - if (!len) { - vq_err(vq, "Unexpected header len for TX: %zd expected %zd\n", - len, hdr_size); - break; - } zcopy_used = zcopy && len >= VHOST_GOODCOPY_LEN && !vhost_exceeds_maxpend(net) -- 2.7.4
Introduce tx_can_batch() to determine whether TX could be batched. This will help to reduce the code duplication in the future. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index a014ca0..f59b615 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -514,6 +514,12 @@ static int get_tx_bufs(struct vhost_net *net, return ret; } +static bool tx_can_batch(struct vhost_virtqueue *vq, size_t total_len) +{ + return total_len < VHOST_NET_WEIGHT && + !vhost_vq_avail_empty(vq->dev, vq); +} + /* Expects to be always run from workqueue - which acts as * read-size critical section for our kind of RCU. */ static void handle_tx(struct vhost_net *net) @@ -598,8 +604,7 @@ static void handle_tx(struct vhost_net *net) ubufs = NULL; } total_len += len; - if (total_len < VHOST_NET_WEIGHT && - !vhost_vq_avail_empty(&net->dev, vq) && + if (tx_can_batch(vq, total_len) && likely(!vhost_exceeds_maxpend(net))) { msg.msg_flags |= MSG_MORE; } else { -- 2.7.4
Instead of mixing zerocopy and datacopy logics, this patch tries to split datacopy logic out. This results for a more compact code and ad-hoc optimization could be done on top more easily. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 110 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 90 insertions(+), 20 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index f59b615..9cef0b2 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -520,9 +520,7 @@ static bool tx_can_batch(struct vhost_virtqueue *vq, size_t total_len) !vhost_vq_avail_empty(vq->dev, vq); } -/* Expects to be always run from workqueue - which acts as - * read-size critical section for our kind of RCU. */ -static void handle_tx(struct vhost_net *net) +static void handle_tx_copy(struct vhost_net *net, struct socket *sock) { struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_TX]; struct vhost_virtqueue *vq = &nvq->vq; @@ -537,30 +535,76 @@ static void handle_tx(struct vhost_net *net) }; size_t len, total_len = 0; int err; - struct socket *sock; - struct vhost_net_ubuf_ref *uninitialized_var(ubufs); - bool zcopy, zcopy_used; int sent_pkts = 0; - mutex_lock(&vq->mutex); - sock = vq->private_data; - if (!sock) - goto out; + for (;;) { + bool busyloop_intr = false; - if (!vq_iotlb_prefetch(vq)) - goto out; + head = get_tx_bufs(net, nvq, &msg, &out, &in, &len, + &busyloop_intr); + /* On error, stop handling until the next kick. */ + if (unlikely(head < 0)) + break; + /* Nothing new? Wait for eventfd to tell us they refilled. */ + if (head == vq->num) { + if (unlikely(busyloop_intr)) { + vhost_poll_queue(&vq->poll); + } else if (unlikely(vhost_enable_notify(&net->dev, + vq))) { + vhost_disable_notify(&net->dev, vq); + continue; + } + break; + } - vhost_disable_notify(&net->dev, vq); - vhost_net_disable_vq(net, vq); + total_len += len; + if (tx_can_batch(vq, total_len)) + msg.msg_flags |= MSG_MORE; + else + msg.msg_flags &= ~MSG_MORE; + + /* TODO: Check specific error and bomb out unless ENOBUFS? */ + err = sock->ops->sendmsg(sock, &msg, len); + if (unlikely(err < 0)) { + vhost_discard_vq_desc(vq, 1); + vhost_net_enable_vq(net, vq); + break; + } + if (err != len) + pr_debug("Truncated TX packet: len %d != %zd\n", + err, len); + vhost_add_used_and_signal(&net->dev, vq, head, 0); + if (vhost_exceeds_weight(++sent_pkts, total_len)) { + vhost_poll_queue(&vq->poll); + break; + } + } +} - zcopy = nvq->ubufs; +static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) +{ + struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_TX]; + struct vhost_virtqueue *vq = &nvq->vq; + unsigned out, in; + int head; + struct msghdr msg = { + .msg_name = NULL, + .msg_namelen = 0, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = MSG_DONTWAIT, + }; + size_t len, total_len = 0; + int err; + struct vhost_net_ubuf_ref *uninitialized_var(ubufs); + bool zcopy_used; + int sent_pkts = 0; for (;;) { bool busyloop_intr; /* Release DMAs done buffers first */ - if (zcopy) - vhost_zerocopy_signal_used(net, vq); + vhost_zerocopy_signal_used(net, vq); busyloop_intr = false; head = get_tx_bufs(net, nvq, &msg, &out, &in, &len, @@ -579,9 +623,9 @@ static void handle_tx(struct vhost_net *net) break; } - zcopy_used = zcopy && len >= VHOST_GOODCOPY_LEN - && !vhost_exceeds_maxpend(net) - && vhost_net_tx_select_zcopy(net); + zcopy_used = len >= VHOST_GOODCOPY_LEN + && !vhost_exceeds_maxpend(net) + && vhost_net_tx_select_zcopy(net); /* use msg_control to pass vhost zerocopy ubuf info to skb */ if (zcopy_used) { @@ -636,6 +680,32 @@ static void handle_tx(struct vhost_net *net) break; } } +} + +/* Expects to be always run from workqueue - which acts as + * read-size critical section for our kind of RCU. */ +static void handle_tx(struct vhost_net *net) +{ + struct vhost_net_virtqueue *nvq = &net->vqs[VHOST_NET_VQ_TX]; + struct vhost_virtqueue *vq = &nvq->vq; + struct socket *sock; + + mutex_lock(&vq->mutex); + sock = vq->private_data; + if (!sock) + goto out; + + if (!vq_iotlb_prefetch(vq)) + goto out; + + vhost_disable_notify(&net->dev, vq); + vhost_net_disable_vq(net, vq); + + if (vhost_sock_zcopy(sock)) + handle_tx_zerocopy(net, sock); + else + handle_tx_copy(net, sock); + out: mutex_unlock(&vq->mutex); } -- 2.7.4
Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 7/9] vhost_net: rename vhost_rx_signal_used() to vhost_net_signal_used()
Rename for reusing this for TX. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 9cef0b2..53d305b 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -741,7 +741,7 @@ static int sk_has_rx_data(struct sock *sk) return skb_queue_empty(&sk->sk_receive_queue); } -static void vhost_rx_signal_used(struct vhost_net_virtqueue *nvq) +static void vhost_net_signal_used(struct vhost_net_virtqueue *nvq) { struct vhost_virtqueue *vq = &nvq->vq; struct vhost_dev *dev = vq->dev; @@ -765,7 +765,7 @@ static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk, if (!len && tvq->busyloop_timeout) { /* Flush batched heads first */ - vhost_rx_signal_used(rnvq); + vhost_net_signal_used(rnvq); /* Both tx vq and rx socket were polled here */ mutex_lock_nested(&tvq->mutex, 1); vhost_disable_notify(&net->dev, tvq); @@ -1008,7 +1008,7 @@ static void handle_rx(struct vhost_net *net) } nvq->done_idx += headcount; if (nvq->done_idx > VHOST_RX_BATCH) - vhost_rx_signal_used(nvq); + vhost_net_signal_used(nvq); if (unlikely(vq_log)) vhost_log_write(vq, vq_log, log, vhost_len); total_len += vhost_len; @@ -1022,7 +1022,7 @@ static void handle_rx(struct vhost_net *net) else vhost_net_enable_vq(net, vq); out: - vhost_rx_signal_used(nvq); + vhost_net_signal_used(nvq); mutex_unlock(&vq->mutex); } -- 2.7.4
Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 8/9] vhost_net: rename VHOST_RX_BATCH to VHOST_NET_BATCH
A more generic name which could be used for TX as well. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 53d305b..2fd2f0e3 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -94,7 +94,7 @@ struct vhost_net_ubuf_ref { struct vhost_virtqueue *vq; }; -#define VHOST_RX_BATCH 64 +#define VHOST_NET_BATCH 64 struct vhost_net_buf { void **queue; int tail; @@ -168,7 +168,7 @@ static int vhost_net_buf_produce(struct vhost_net_virtqueue *nvq) rxq->head = 0; rxq->tail = ptr_ring_consume_batched(nvq->rx_ring, rxq->queue, - VHOST_RX_BATCH); + VHOST_NET_BATCH); return rxq->tail; } @@ -1007,7 +1007,7 @@ static void handle_rx(struct vhost_net *net) goto out; } nvq->done_idx += headcount; - if (nvq->done_idx > VHOST_RX_BATCH) + if (nvq->done_idx > VHOST_NET_BATCH) vhost_net_signal_used(nvq); if (unlikely(vq_log)) vhost_log_write(vq, vq_log, log, vhost_len); @@ -1075,7 +1075,7 @@ static int vhost_net_open(struct inode *inode, struct file *f) return -ENOMEM; } - queue = kmalloc_array(VHOST_RX_BATCH, sizeof(void *), + queue = kmalloc_array(VHOST_NET_BATCH, sizeof(void *), GFP_KERNEL); if (!queue) { kfree(vqs); -- 2.7.4
Jason Wang
2018-Jul-20 00:15 UTC
[PATCH net-next 9/9] vhost_net: batch update used ring for datacopy TX
Like commit e2b3b35eb989 ("vhost_net: batch used ring update in rx"), this patches implements batch used ring update for datacopy TX (zerocopy has already done some kind of batching). Testpmd transmission from guest to host (XDP_DROP on tap) shows 25.8% improvement (from ~3.1Mpps to ~3.9Mpps) on Broadwell i7-5600U CPU @ 2.60GHz machine. Netperf TCP tests does not show obvious differences. Signed-off-by: Jason Wang <jasowang at redhat.com> --- drivers/vhost/net.c | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 2fd2f0e3..367d802 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c @@ -428,16 +428,31 @@ static int vhost_net_enable_vq(struct vhost_net *n, return vhost_poll_start(poll, sock->file); } +static void vhost_net_signal_used(struct vhost_net_virtqueue *nvq) +{ + struct vhost_virtqueue *vq = &nvq->vq; + struct vhost_dev *dev = vq->dev; + + if (!nvq->done_idx) + return; + + vhost_add_used_and_signal_n(dev, vq, vq->heads, nvq->done_idx); + nvq->done_idx = 0; +} + static int vhost_net_tx_get_vq_desc(struct vhost_net *net, - struct vhost_virtqueue *vq, + struct vhost_net_virtqueue *nvq, unsigned int *out_num, unsigned int *in_num, bool *busyloop_intr) { + struct vhost_virtqueue *vq = &nvq->vq; unsigned long uninitialized_var(endtime); int r = vhost_get_vq_desc(vq, vq->iov, ARRAY_SIZE(vq->iov), out_num, in_num, NULL, NULL); if (r == vq->num && vq->busyloop_timeout) { + if (!vhost_sock_zcopy(vq->private_data)) + vhost_net_signal_used(nvq); preempt_disable(); endtime = busy_clock() + vq->busyloop_timeout; while (vhost_can_busy_poll(endtime)) { @@ -493,7 +508,8 @@ static int get_tx_bufs(struct vhost_net *net, struct vhost_virtqueue *vq = &nvq->vq; int ret; - ret = vhost_net_tx_get_vq_desc(net, vq, out, in, busyloop_intr); + ret = vhost_net_tx_get_vq_desc(net, nvq, out, in, busyloop_intr); + if (ret < 0 || ret == vq->num) return ret; @@ -557,6 +573,9 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock) break; } + vq->heads[nvq->done_idx].id = cpu_to_vhost32(vq, head); + vq->heads[nvq->done_idx].len = 0; + total_len += len; if (tx_can_batch(vq, total_len)) msg.msg_flags |= MSG_MORE; @@ -573,12 +592,15 @@ static void handle_tx_copy(struct vhost_net *net, struct socket *sock) if (err != len) pr_debug("Truncated TX packet: len %d != %zd\n", err, len); - vhost_add_used_and_signal(&net->dev, vq, head, 0); + if (++nvq->done_idx >= VHOST_NET_BATCH) + vhost_net_signal_used(nvq); if (vhost_exceeds_weight(++sent_pkts, total_len)) { vhost_poll_queue(&vq->poll); break; } } + + vhost_net_signal_used(nvq); } static void handle_tx_zerocopy(struct vhost_net *net, struct socket *sock) @@ -741,18 +763,6 @@ static int sk_has_rx_data(struct sock *sk) return skb_queue_empty(&sk->sk_receive_queue); } -static void vhost_net_signal_used(struct vhost_net_virtqueue *nvq) -{ - struct vhost_virtqueue *vq = &nvq->vq; - struct vhost_dev *dev = vq->dev; - - if (!nvq->done_idx) - return; - - vhost_add_used_and_signal_n(dev, vq, vq->heads, nvq->done_idx); - nvq->done_idx = 0; -} - static int vhost_net_rx_peek_head_len(struct vhost_net *net, struct sock *sk, bool *busyloop_intr) { -- 2.7.4
David Miller
2018-Jul-22 04:44 UTC
[PATCH net-next 0/9] TX used ring batched updating for vhost
From: Jason Wang <jasowang at redhat.com> Date: Fri, 20 Jul 2018 08:15:12 +0800> This series implement batch updating of used ring for TX. This help to > reduce the cache contention on used ring. The idea is first split > datacopy path from zerocopy, and do only batching for datacopy. This > is because zercopy had already supported its own batching. > > TX PPS was increased 25.8% and Netperf TCP does not show obvious > differences. > > The split of datapath will also be helpful for future implementation > like in order completion. > > Please review.Jason, I really like the way you composed this patch series, it was very easy to read and understand. :-) Michael, please review.
Michael S. Tsirkin
2018-Jul-22 14:37 UTC
[PATCH net-next 0/9] TX used ring batched updating for vhost
On Fri, Jul 20, 2018 at 08:15:12AM +0800, Jason Wang wrote:> Hi: > > This series implement batch updating of used ring for TX. This help to > reduce the cache contention on used ring. The idea is first split > datacopy path from zerocopy, and do only batching for datacopy. This > is because zercopy had already supported its own batching. > > TX PPS was increased 25.8% and Netperf TCP does not show obvious > differences. > > The split of datapath will also be helpful for future implementation > like in order completion. > > Please review. > > ThanksAcked-by: Michael S. Tsirkin <mst at redhat.com> I'm very happy with the split, the mixed data path became hard to maintain.> Jason Wang (9): > vhost_net: drop unnecessary parameter > vhost_net: introduce helper to initialize tx iov iter > vhost_net: introduce vhost_exceeds_weight() > vhost_net: introduce get_tx_bufs() > vhost_net: introduce tx_can_batch() > vhost_net: split out datacopy logic > vhost_net: rename vhost_rx_signal_used() to vhost_net_signal_used() > vhost_net: rename VHOST_RX_BATCH to VHOST_NET_BATCH > vhost_net: batch update used ring for datacopy TX > > drivers/vhost/net.c | 249 +++++++++++++++++++++++++++++++++++++--------------- > 1 file changed, 179 insertions(+), 70 deletions(-) > > -- > 2.7.4
David Miller
2018-Jul-22 16:44 UTC
[PATCH net-next 0/9] TX used ring batched updating for vhost
From: "Michael S. Tsirkin" <mst at redhat.com> Date: Sun, 22 Jul 2018 17:37:05 +0300> On Fri, Jul 20, 2018 at 08:15:12AM +0800, Jason Wang wrote: >> Hi: >> >> This series implement batch updating of used ring for TX. This help to >> reduce the cache contention on used ring. The idea is first split >> datacopy path from zerocopy, and do only batching for datacopy. This >> is because zercopy had already supported its own batching. >> >> TX PPS was increased 25.8% and Netperf TCP does not show obvious >> differences. >> >> The split of datapath will also be helpful for future implementation >> like in order completion. >> >> Please review. >> >> Thanks > > Acked-by: Michael S. Tsirkin <mst at redhat.com> > > I'm very happy with the split, the mixed data path became hard to > maintain.Thanks for reviewing. Series applied, thanks everyone.
Possibly Parallel Threads
- [PATCH net-next 0/9] TX used ring batched updating for vhost
- [PATCH net-next 11/11] vhost_net: batch submitting XDP buffers to underlayer sockets
- [PATCH net-next 11/11] vhost_net: batch submitting XDP buffers to underlayer sockets
- [PATCH net-next 11/11] vhost_net: batch submitting XDP buffers to underlayer sockets
- [PATCH RFC 08/13] vhost/net: convert to new API: heads->bufs