From: Jason Wang <hidden> Date: 2013-08-16 05:27:57
Hi all:
This series tries to unify and simplify vhost codes especially for zerocopy.
Plase review.
Thanks
Jason Wang (6):
vhost_net: make vhost_zerocopy_signal_used() returns void
vhost_net: use vhost_add_used_and_signal_n() in
vhost_zerocopy_signal_used()
vhost: switch to use vhost_add_used_n()
vhost_net: determine whether or not to use zerocopy at one time
vhost_net: poll vhost queue after marking DMA is done
vhost_net: remove the max pending check
drivers/vhost/net.c | 86 +++++++++++++++++++-----------------------------
drivers/vhost/vhost.c | 43 +-----------------------
2 files changed, 36 insertions(+), 93 deletions(-)
From: Jason Wang <hidden> Date: 2013-08-16 05:28:05
None of its caller use its return value, so let it return void.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 5 ++---
1 files changed, 2 insertions(+), 3 deletions(-)
From: Jason Wang <hidden> Date: 2013-08-16 05:28:50
Switch to use vhost_add_used_and_signal_n() to avoid multiple calls to
vhost_add_used_and_signal(). With the patch we will call at most 2 times
(consider done_idx warp around) compared to N times w/o this patch.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 13 ++++++++-----
1 files changed, 8 insertions(+), 5 deletions(-)
From: Jason Wang <hidden> Date: 2013-08-16 05:28:55
Let vhost_add_used() to use vhost_add_used_n() to reduce the code duplication.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/vhost.c | 43 ++-----------------------------------------
1 files changed, 2 insertions(+), 41 deletions(-)
@@ -1332,48 +1332,9 @@ EXPORT_SYMBOL_GPL(vhost_discard_vq_desc);*wanttonotifytheguest,usingeventfd.*/intvhost_add_used(structvhost_virtqueue*vq,unsignedinthead,intlen){-structvring_used_elem__user*used;+structvring_used_elemheads={head,len};-/* The virtqueue contains a ring of used buffers. Get a pointer to the-*nextentryinthatusedring.*/-used=&vq->used->ring[vq->last_used_idx%vq->num];-if(__put_user(head,&used->id)){-vq_err(vq,"Failed to write used id");-return-EFAULT;-}-if(__put_user(len,&used->len)){-vq_err(vq,"Failed to write used len");-return-EFAULT;-}-/* Make sure buffer is written before we update index. */-smp_wmb();-if(__put_user(vq->last_used_idx+1,&vq->used->idx)){-vq_err(vq,"Failed to increment used idx");-return-EFAULT;-}-if(unlikely(vq->log_used)){-/* Make sure data is seen before log. */-smp_wmb();-/* Log used ring entry write. */-log_write(vq->log_base,-vq->log_addr+-((void__user*)used-(void__user*)vq->used),-sizeof*used);-/* Log used index update. */-log_write(vq->log_base,-vq->log_addr+offsetof(structvring_used,idx),-sizeofvq->used->idx);-if(vq->log_ctx)-eventfd_signal(vq->log_ctx,1);-}-vq->last_used_idx++;-/* If the driver never bothers to signal in a very long while,-*usedindexmightwraparound.Ifthathappens,invalidate-*signalled_usedindexwestored.TODO:makesuredriver-*signalsatleastoncein2^16andremovethis.*/-if(unlikely(vq->last_used_idx==vq->signalled_used))-vq->signalled_used_valid=false;-return0;+returnvhost_add_used_n(vq,&heads,1);}EXPORT_SYMBOL_GPL(vhost_add_used);
From: Jason Wang <hidden> Date: 2013-08-16 05:29:01
Currently, even if the packet length is smaller than VHOST_GOODCOPY_LEN, if
upend_idx != done_idx we still set zcopy_used to true and rollback this choice
later. This could be avoided by determine zerocopy once by checking all
conditions at one time before.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 46 +++++++++++++++++++---------------------------
1 files changed, 19 insertions(+), 27 deletions(-)
@@ -404,43 +404,35 @@ static void handle_tx(struct vhost_net *net)iov_length(nvq->hdr,s),hdr_size);break;}-zcopy_used=zcopy&&(len>=VHOST_GOODCOPY_LEN||-nvq->upend_idx!=nvq->done_idx);++zcopy_used=zcopy&&len>=VHOST_GOODCOPY_LEN+&&nvq->upend_idx!=nvq->done_idx+&&vhost_net_tx_select_zcopy(net);/* use msg_control to pass vhost zerocopy ubuf info to skb */if(zcopy_used){+structubuf_info*ubuf;+ubuf=nvq->ubuf_info+nvq->upend_idx;+vq->heads[nvq->upend_idx].id=head;-if(!vhost_net_tx_select_zcopy(net)||-len<VHOST_GOODCOPY_LEN){-/* copy don't need to wait for DMA done */-vq->heads[nvq->upend_idx].len=-VHOST_DMA_DONE_LEN;-msg.msg_control=NULL;-msg.msg_controllen=0;-ubufs=NULL;-}else{-structubuf_info*ubuf;-ubuf=nvq->ubuf_info+nvq->upend_idx;--vq->heads[nvq->upend_idx].len=-VHOST_DMA_IN_PROGRESS;-ubuf->callback=vhost_zerocopy_callback;-ubuf->ctx=nvq->ubufs;-ubuf->desc=nvq->upend_idx;-msg.msg_control=ubuf;-msg.msg_controllen=sizeof(ubuf);-ubufs=nvq->ubufs;-kref_get(&ubufs->kref);-}+vq->heads[nvq->upend_idx].len=VHOST_DMA_IN_PROGRESS;+ubuf->callback=vhost_zerocopy_callback;+ubuf->ctx=nvq->ubufs;+ubuf->desc=nvq->upend_idx;+msg.msg_control=ubuf;+msg.msg_controllen=sizeof(ubuf);+ubufs=nvq->ubufs;+kref_get(&ubufs->kref);nvq->upend_idx=(nvq->upend_idx+1)%UIO_MAXIOV;-}else+}else{msg.msg_control=NULL;+ubufs=NULL;+}/* TODO: Check specific error and bomb out unless ENOBUFS? */err=sock->ops->sendmsg(NULL,sock,&msg,len);if(unlikely(err<0)){if(zcopy_used){-if(ubufs)-vhost_net_ubuf_put(ubufs);+vhost_net_ubuf_put(ubufs);nvq->upend_idx=((unsigned)nvq->upend_idx-1)%UIO_MAXIOV;}
From: Jason Wang <hidden> Date: 2013-08-16 05:29:06
We used to poll vhost queue before making DMA is done, this is racy if vhost
thread were waked up before marking DMA is done which can result the signal to
be missed. Fix this by always poll the vhost thread before DMA is done.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 9 +++++----
1 files changed, 5 insertions(+), 4 deletions(-)
@@ -308,6 +308,11 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)structvhost_virtqueue*vq=ubufs->vq;intcnt=atomic_read(&ubufs->kref.refcount);+/* set len to mark this desc buffers done DMA */+vq->heads[ubuf->desc].len=success?+VHOST_DMA_DONE_LEN:VHOST_DMA_FAILED_LEN;+vhost_net_ubuf_put(ubufs);+/**Triggerpollingthreadifgueststoppedsubmittingnewbuffers:*inthiscase,therefcountafterdecrementwilleventuallyreach1
@@ -318,10 +323,6 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)*/if(cnt<=2||!(cnt%16))vhost_poll_queue(&vq->poll);-/* set len to mark this desc buffers done DMA */-vq->heads[ubuf->desc].len=success?-VHOST_DMA_DONE_LEN:VHOST_DMA_FAILED_LEN;-vhost_net_ubuf_put(ubufs);}/* Expects to be always run from workqueue - which acts as
From: Jason Wang <hidden> Date: 2013-08-16 05:29:10
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
So remove this check completely.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 13 -------------
1 files changed, 0 insertions(+), 13 deletions(-)
@@ -38,8 +38,6 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"*Usingthislimitpreventsonevirtqueuefromstarvingothers.*/#define VHOST_NET_WEIGHT 0x80000-/* MAX number of TX used buffers for outstanding zerocopy */-#define VHOST_MAX_PEND 128#define VHOST_GOODCOPY_LEN 256/*
@@ -372,17 +370,6 @@ static void handle_tx(struct vhost_net *net)break;/* Nothing new? Wait for eventfd to tell us they refilled. */if(head==vq->num){-intnum_pends;--/* If more outstanding DMAs, queue the work.-*Handleupend_idxwraparound-*/-num_pends=likely(nvq->upend_idx>=nvq->done_idx)?-(nvq->upend_idx-nvq->done_idx):-(nvq->upend_idx+UIO_MAXIOV--nvq->done_idx);-if(unlikely(num_pends>VHOST_MAX_PEND))-break;if(unlikely(vhost_enable_notify(&net->dev,vq))){vhost_disable_notify(&net->dev,vq);continue;
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2013-08-16 09:52:46
On Fri, Aug 16, 2013 at 01:16:26PM +0800, Jason Wang wrote:
Switch to use vhost_add_used_and_signal_n() to avoid multiple calls to
vhost_add_used_and_signal(). With the patch we will call at most 2 times
(consider done_idx warp around) compared to N times w/o this patch.
Signed-off-by: Jason Wang <redacted>
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2013-08-16 09:55:17
On Fri, Aug 16, 2013 at 01:16:27PM +0800, Jason Wang wrote:
Let vhost_add_used() to use vhost_add_used_n() to reduce the code duplication.
Signed-off-by: Jason Wang <redacted>
Does compiler inline it then?
Reason I ask, last time I checked put_user inside vhost_add_used
was much cheaper than copy_to_user inside vhost_add_used_n,
so I wouldn't be surprised if this hurt performance.
Did you check?
@@ -1332,48 +1332,9 @@ EXPORT_SYMBOL_GPL(vhost_discard_vq_desc);*wanttonotifytheguest,usingeventfd.*/intvhost_add_used(structvhost_virtqueue*vq,unsignedinthead,intlen){-structvring_used_elem__user*used;+structvring_used_elemheads={head,len};-/* The virtqueue contains a ring of used buffers. Get a pointer to the-*nextentryinthatusedring.*/-used=&vq->used->ring[vq->last_used_idx%vq->num];-if(__put_user(head,&used->id)){-vq_err(vq,"Failed to write used id");-return-EFAULT;-}-if(__put_user(len,&used->len)){-vq_err(vq,"Failed to write used len");-return-EFAULT;-}-/* Make sure buffer is written before we update index. */-smp_wmb();-if(__put_user(vq->last_used_idx+1,&vq->used->idx)){-vq_err(vq,"Failed to increment used idx");-return-EFAULT;-}-if(unlikely(vq->log_used)){-/* Make sure data is seen before log. */-smp_wmb();-/* Log used ring entry write. */-log_write(vq->log_base,-vq->log_addr+-((void__user*)used-(void__user*)vq->used),-sizeof*used);-/* Log used index update. */-log_write(vq->log_base,-vq->log_addr+offsetof(structvring_used,idx),-sizeofvq->used->idx);-if(vq->log_ctx)-eventfd_signal(vq->log_ctx,1);-}-vq->last_used_idx++;-/* If the driver never bothers to signal in a very long while,-*usedindexmightwraparound.Ifthathappens,invalidate-*signalled_usedindexwestored.TODO:makesuredriver-*signalsatleastoncein2^16andremovethis.*/-if(unlikely(vq->last_used_idx==vq->signalled_used))-vq->signalled_used_valid=false;-return0;+returnvhost_add_used_n(vq,&heads,1);}EXPORT_SYMBOL_GPL(vhost_add_used);
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2013-08-16 09:59:14
On Fri, Aug 16, 2013 at 01:16:29PM +0800, Jason Wang wrote:
We used to poll vhost queue before making DMA is done, this is racy if vhost
thread were waked up before marking DMA is done which can result the signal to
be missed. Fix this by always poll the vhost thread before DMA is done.
Signed-off-by: Jason Wang <redacted>
Indeed, but vhost_net_ubuf_put should be the last thing we do:
it can cause the device to go away and we'll get
a user after free.
@@ -308,6 +308,11 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)structvhost_virtqueue*vq=ubufs->vq;intcnt=atomic_read(&ubufs->kref.refcount);+/* set len to mark this desc buffers done DMA */+vq->heads[ubuf->desc].len=success?+VHOST_DMA_DONE_LEN:VHOST_DMA_FAILED_LEN;+vhost_net_ubuf_put(ubufs);+/**Triggerpollingthreadifgueststoppedsubmittingnewbuffers:*inthiscase,therefcountafterdecrementwilleventuallyreach1
@@ -318,10 +323,6 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)*/if(cnt<=2||!(cnt%16))vhost_poll_queue(&vq->poll);-/* set len to mark this desc buffers done DMA */-vq->heads[ubuf->desc].len=success?-VHOST_DMA_DONE_LEN:VHOST_DMA_FAILED_LEN;-vhost_net_ubuf_put(ubufs);}/* Expects to be always run from workqueue - which acts as
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2013-08-16 10:00:45
On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
We can but performance will suffer.
quoted hunk
So remove this check completely.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 13 -------------
1 files changed, 0 insertions(+), 13 deletions(-)
@@ -38,8 +38,6 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"*Usingthislimitpreventsonevirtqueuefromstarvingothers.*/#define VHOST_NET_WEIGHT 0x80000-/* MAX number of TX used buffers for outstanding zerocopy */-#define VHOST_MAX_PEND 128#define VHOST_GOODCOPY_LEN 256/*
@@ -372,17 +370,6 @@ static void handle_tx(struct vhost_net *net)break;/* Nothing new? Wait for eventfd to tell us they refilled. */if(head==vq->num){-intnum_pends;--/* If more outstanding DMAs, queue the work.-*Handleupend_idxwraparound-*/-num_pends=likely(nvq->upend_idx>=nvq->done_idx)?-(nvq->upend_idx-nvq->done_idx):-(nvq->upend_idx+UIO_MAXIOV--nvq->done_idx);-if(unlikely(num_pends>VHOST_MAX_PEND))-break;if(unlikely(vhost_enable_notify(&net->dev,vq))){vhost_disable_notify(&net->dev,vq);continue;
From: Jason Wang <hidden> Date: 2013-08-20 02:33:14
On 08/16/2013 05:54 PM, Michael S. Tsirkin wrote:
On Fri, Aug 16, 2013 at 01:16:26PM +0800, Jason Wang wrote:
quoted
quoted
Switch to use vhost_add_used_and_signal_n() to avoid multiple calls to
vhost_add_used_and_signal(). With the patch we will call at most 2 times
(consider done_idx warp around) compared to N times w/o this patch.
Signed-off-by: Jason Wang <redacted>
So? Does this help performance then?
Looks like it can especially when guest does support event index. When
guest enable tx interrupt, this can saves us some unnecessary signal to
guest. I will do some test.
From: Jason Wang <hidden> Date: 2013-08-20 02:36:23
On 08/16/2013 05:56 PM, Michael S. Tsirkin wrote:
On Fri, Aug 16, 2013 at 01:16:27PM +0800, Jason Wang wrote:
quoted
quoted
Let vhost_add_used() to use vhost_add_used_n() to reduce the code duplication.
Signed-off-by: Jason Wang <redacted>
Does compiler inline it then?
Reason I ask, last time I checked put_user inside vhost_add_used
was much cheaper than copy_to_user inside vhost_add_used_n,
so I wouldn't be surprised if this hurt performance.
Did you check?
I run virtio_test but didn't see the difference.
Did you mean the might_fault() in __copy_to_user()? So how about switch
to use __put_user() if count is one in __vhost_add_used_n()?
From: Jason Wang <hidden> Date: 2013-08-20 02:44:49
On 08/16/2013 06:00 PM, Michael S. Tsirkin wrote:
On Fri, Aug 16, 2013 at 01:16:29PM +0800, Jason Wang wrote:
quoted
We used to poll vhost queue before making DMA is done, this is racy if vhost
thread were waked up before marking DMA is done which can result the signal to
be missed. Fix this by always poll the vhost thread before DMA is done.
Signed-off-by: Jason Wang <redacted>
Indeed, but vhost_net_ubuf_put should be the last thing we do:
it can cause the device to go away and we'll get
a user after free.
Didn't get this. We didn't use ubuf in vhost_zerocopy_signal_used(),
looks safe here?
@@ -308,6 +308,11 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)structvhost_virtqueue*vq=ubufs->vq;intcnt=atomic_read(&ubufs->kref.refcount);+/* set len to mark this desc buffers done DMA */+vq->heads[ubuf->desc].len=success?+VHOST_DMA_DONE_LEN:VHOST_DMA_FAILED_LEN;+vhost_net_ubuf_put(ubufs);+/**Triggerpollingthreadifgueststoppedsubmittingnewbuffers:*inthiscase,therefcountafterdecrementwilleventuallyreach1
@@ -318,10 +323,6 @@ static void vhost_zerocopy_callback(struct ubuf_info *ubuf, bool success)*/if(cnt<=2||!(cnt%16))vhost_poll_queue(&vq->poll);-/* set len to mark this desc buffers done DMA */-vq->heads[ubuf->desc].len=success?-VHOST_DMA_DONE_LEN:VHOST_DMA_FAILED_LEN;-vhost_net_ubuf_put(ubufs);}/* Expects to be always run from workqueue - which acts as
From: Jason Wang <hidden> Date: 2013-08-20 02:48:32
On 08/16/2013 06:02 PM, Michael S. Tsirkin wrote:
On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
quoted
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
We can but performance will suffer.
The check were in fact only done when no new buffers submitted from
guest. So if guest keep sending, the check won't be done.
If we really want to do this, we should do it unconditionally. Anyway, I
will do test to see the result.
quoted
So remove this check completely.
Signed-off-by: Jason Wang <redacted>
---
drivers/vhost/net.c | 13 -------------
1 files changed, 0 insertions(+), 13 deletions(-)
@@ -38,8 +38,6 @@ MODULE_PARM_DESC(experimental_zcopytx, "Enable Zero Copy TX;"*Usingthislimitpreventsonevirtqueuefromstarvingothers.*/#define VHOST_NET_WEIGHT 0x80000-/* MAX number of TX used buffers for outstanding zerocopy */-#define VHOST_MAX_PEND 128#define VHOST_GOODCOPY_LEN 256/*
@@ -372,17 +370,6 @@ static void handle_tx(struct vhost_net *net)break;/* Nothing new? Wait for eventfd to tell us they refilled. */if(head==vq->num){-intnum_pends;--/* If more outstanding DMAs, queue the work.-*Handleupend_idxwraparound-*/-num_pends=likely(nvq->upend_idx>=nvq->done_idx)?-(nvq->upend_idx-nvq->done_idx):-(nvq->upend_idx+UIO_MAXIOV--nvq->done_idx);-if(unlikely(num_pends>VHOST_MAX_PEND))-break;if(unlikely(vhost_enable_notify(&net->dev,vq))){vhost_disable_notify(&net->dev,vq);continue;
From: Jason Wang <hidden> Date: 2013-08-23 08:50:48
On 08/20/2013 10:33 AM, Jason Wang wrote:
On 08/16/2013 05:54 PM, Michael S. Tsirkin wrote:
quoted
On Fri, Aug 16, 2013 at 01:16:26PM +0800, Jason Wang wrote:
quoted
quoted
Switch to use vhost_add_used_and_signal_n() to avoid multiple calls to
vhost_add_used_and_signal(). With the patch we will call at most 2 times
(consider done_idx warp around) compared to N times w/o this patch.
Signed-off-by: Jason Wang <redacted>
So? Does this help performance then?
Looks like it can especially when guest does support event index. When
guest enable tx interrupt, this can saves us some unnecessary signal to
guest. I will do some test.
Have done some test. I can see 2% - 3% increasing in both aggregate
transaction rate and per cpu transaction rate in TCP_RR and UDP_RR test.
I'm using ixgbe. W/o this patch, I can see more than 100 calls of
vhost_add_used_signal() in one vhost_zerocopy_signaled_used(). This is
because ixgbe (and other modern ethernet driver) tends to free old tx
skbs in a loop during tx interrupt, and vhost tend to batch the adding
used and signal in vhost_zerocopy_callback(). Switching to use
vhost_add_use_and_signal_n() means saving 100 times of used idx updating
and memory barriers.
From: Jason Wang <hidden> Date: 2013-08-23 08:55:57
On 08/20/2013 10:48 AM, Jason Wang wrote:
On 08/16/2013 06:02 PM, Michael S. Tsirkin wrote:
quoted
quoted
On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
quoted
quoted
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
We can but performance will suffer.
The check were in fact only done when no new buffers submitted from
guest. So if guest keep sending, the check won't be done.
If we really want to do this, we should do it unconditionally. Anyway, I
will do test to see the result.
There's a bug in PATCH 5/6, the check:
nvq->upend_idx != nvq->done_idx
makes the zerocopy always been disabled since we initialize both
upend_idx and done_idx to zero. So I change it to:
(nvq->upend_idx + 1) % UIO_MAXIOV != nvq->done_idx.
With this change on top, I didn't see performance difference w/ and w/o
this patch.
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2013-08-25 11:47:04
On Fri, Aug 23, 2013 at 04:50:38PM +0800, Jason Wang wrote:
On 08/20/2013 10:33 AM, Jason Wang wrote:
quoted
On 08/16/2013 05:54 PM, Michael S. Tsirkin wrote:
quoted
On Fri, Aug 16, 2013 at 01:16:26PM +0800, Jason Wang wrote:
quoted
quoted
Switch to use vhost_add_used_and_signal_n() to avoid multiple calls to
vhost_add_used_and_signal(). With the patch we will call at most 2 times
(consider done_idx warp around) compared to N times w/o this patch.
Signed-off-by: Jason Wang <redacted>
So? Does this help performance then?
Looks like it can especially when guest does support event index. When
guest enable tx interrupt, this can saves us some unnecessary signal to
guest. I will do some test.
Have done some test. I can see 2% - 3% increasing in both aggregate
transaction rate and per cpu transaction rate in TCP_RR and UDP_RR test.
I'm using ixgbe. W/o this patch, I can see more than 100 calls of
vhost_add_used_signal() in one vhost_zerocopy_signaled_used(). This is
because ixgbe (and other modern ethernet driver) tends to free old tx
skbs in a loop during tx interrupt, and vhost tend to batch the adding
used and signal in vhost_zerocopy_callback(). Switching to use
vhost_add_use_and_signal_n() means saving 100 times of used idx updating
and memory barriers.
Well it's only smp_wmb so a nop on most architectures, so
a 2% gain is surprising.
I'm guessing the cache miss on the write is what's
giving us a speedup here.
I'll review the code, thanks.
--
MST
From: "Michael S. Tsirkin" <mst@redhat.com> Date: 2013-08-25 11:51:55
On Fri, Aug 23, 2013 at 04:55:49PM +0800, Jason Wang wrote:
On 08/20/2013 10:48 AM, Jason Wang wrote:
quoted
On 08/16/2013 06:02 PM, Michael S. Tsirkin wrote:
quoted
quoted
On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
quoted
quoted
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
We can but performance will suffer.
The check were in fact only done when no new buffers submitted from
guest. So if guest keep sending, the check won't be done.
If we really want to do this, we should do it unconditionally. Anyway, I
will do test to see the result.
There's a bug in PATCH 5/6, the check:
nvq->upend_idx != nvq->done_idx
makes the zerocopy always been disabled since we initialize both
upend_idx and done_idx to zero. So I change it to:
(nvq->upend_idx + 1) % UIO_MAXIOV != nvq->done_idx.
But what I would really like to try is limit ubuf_info to VHOST_MAX_PEND.
I think this has a chance to improve performance since
we'll be using less cache.
Of course this means we must fix the code to really never submit
more than VHOST_MAX_PEND requests.
Want to try?
With this change on top, I didn't see performance difference w/ and w/o
this patch.
Did you try small message sizes btw (like 1K)? Or just netperf
default of 64K?
--
MST
From: Jason Wang <hidden> Date: 2013-08-26 07:00:42
On 08/25/2013 07:53 PM, Michael S. Tsirkin wrote:
On Fri, Aug 23, 2013 at 04:55:49PM +0800, Jason Wang wrote:
quoted
On 08/20/2013 10:48 AM, Jason Wang wrote:
quoted
On 08/16/2013 06:02 PM, Michael S. Tsirkin wrote:
quoted
quoted
On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
quoted
quoted
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
We can but performance will suffer.
The check were in fact only done when no new buffers submitted from
guest. So if guest keep sending, the check won't be done.
If we really want to do this, we should do it unconditionally. Anyway, I
will do test to see the result.
There's a bug in PATCH 5/6, the check:
nvq->upend_idx != nvq->done_idx
makes the zerocopy always been disabled since we initialize both
upend_idx and done_idx to zero. So I change it to:
(nvq->upend_idx + 1) % UIO_MAXIOV != nvq->done_idx.
But what I would really like to try is limit ubuf_info to VHOST_MAX_PEND.
I think this has a chance to improve performance since
we'll be using less cache.
Maybe, but it in fact decrease the vq size to VHOST_MAX_PEND.
Of course this means we must fix the code to really never submit
more than VHOST_MAX_PEND requests.
Want to try?
Ok, sure.
quoted
With this change on top, I didn't see performance difference w/ and w/o
this patch.
Did you try small message sizes btw (like 1K)? Or just netperf
default of 64K?
I just test multiple sessions of TCP_RR. Will test TCP_STREAM also.
From: Jason Wang <hidden> Date: 2013-08-30 03:23:23
On 08/25/2013 07:53 PM, Michael S. Tsirkin wrote:
On Fri, Aug 23, 2013 at 04:55:49PM +0800, Jason Wang wrote:
quoted
On 08/20/2013 10:48 AM, Jason Wang wrote:
quoted
On 08/16/2013 06:02 PM, Michael S. Tsirkin wrote:
quoted
quoted
On Fri, Aug 16, 2013 at 01:16:30PM +0800, Jason Wang wrote:
quoted
quoted
We used to limit the max pending DMAs to prevent guest from pinning too many
pages. But this could be removed since:
- We have the sk_wmem_alloc check in both tun/macvtap to do the same work
- This max pending check were almost useless since it was one done when there's
no new buffers coming from guest. Guest can easily exceeds the limitation.
- We've already check upend_idx != done_idx and switch to non zerocopy then. So
even if all vq->heads were used, we can still does the packet transmission.
We can but performance will suffer.
The check were in fact only done when no new buffers submitted from
guest. So if guest keep sending, the check won't be done.
If we really want to do this, we should do it unconditionally. Anyway, I
will do test to see the result.
There's a bug in PATCH 5/6, the check:
nvq->upend_idx != nvq->done_idx
makes the zerocopy always been disabled since we initialize both
upend_idx and done_idx to zero. So I change it to:
(nvq->upend_idx + 1) % UIO_MAXIOV != nvq->done_idx.
But what I would really like to try is limit ubuf_info to VHOST_MAX_PEND.
I think this has a chance to improve performance since
we'll be using less cache.
Of course this means we must fix the code to really never submit
more than VHOST_MAX_PEND requests.
Want to try?
The result is, I see about 5%-10% improvement for per cpu throughput on
guest tx. But about 5% degradation on per cpu transaction rate on TCP_RR.
quoted
With this change on top, I didn't see performance difference w/ and w/o
this patch.
Did you try small message sizes btw (like 1K)? Or just netperf
default of 64K?
5%-10% improvement on for per cpu throughput on guest rx, but some
regressions (5%) on guest tx. So we'd better keep and make it doing
properly.
Will post V2 for your reviewing.