aboutsummaryrefslogtreecommitdiffstats
path: root/Documentation/lguest
diff options
context:
space:
mode:
authorRusty Russell <rusty@rustcorp.com.au>2009-06-13 00:27:12 -0400
committerRusty Russell <rusty@rustcorp.com.au>2009-06-12 08:57:12 -0400
commit4a8962e21bc505c714fc2508494d4c7dd3fe2d29 (patch)
tree55afdb7bc1f7e03bc910e59a17962e671a031ebc /Documentation/lguest
parent95c517c09bad31a03e22f2fdb5f0aa26a490a92d (diff)
lguest: try to batch interrupts on network receive
Rather than triggering an interrupt every time, we only trigger an interrupt when there are no more incoming packets (or the recv queue is full). However, the overhead of doing the select to figure this out is measurable: 1M pings goes from 98 to 104 seconds, and 1G Guest->Host TCP goes from 3.69 to 3.94 seconds. It's close to the noise though. I tested various timeouts, including reducing it as the number of pending packets increased, timing a 1 gigabyte TCP send from Guest -> Host and Host -> Guest (GSO disabled, to increase packet rate). // time tcpblast -o -s 65536 -c 16k 192.168.2.1:9999 > /dev/null Timeout Guest->Host Pkts/irq Host->Guest Pkts/irq Before 11.3s 1.0 6.3s 1.0 0 11.7s 1.0 6.6s 23.5 1 17.1s 8.8 8.6s 26.0 1/pending 13.4s 1.9 6.6s 23.8 2/pending 13.6s 2.8 6.6s 24.1 5/pending 14.1s 5.0 6.6s 24.4 Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Diffstat (limited to 'Documentation/lguest')
-rw-r--r--Documentation/lguest/lguest.c17
1 files changed, 16 insertions, 1 deletions
diff --git a/Documentation/lguest/lguest.c b/Documentation/lguest/lguest.c
index 20f8253881b3..64110797044a 100644
--- a/Documentation/lguest/lguest.c
+++ b/Documentation/lguest/lguest.c
@@ -769,6 +769,16 @@ static void net_output(struct virtqueue *vq)
769 add_used(vq, head, 0); 769 add_used(vq, head, 0);
770} 770}
771 771
772/* Will reading from this file descriptor block? */
773static bool will_block(int fd)
774{
775 fd_set fdset;
776 struct timeval zero = { 0, 0 };
777 FD_ZERO(&fdset);
778 FD_SET(fd, &fdset);
779 return select(fd+1, &fdset, NULL, NULL, &zero) != 1;
780}
781
772/* This is where we handle packets coming in from the tun device to our 782/* This is where we handle packets coming in from the tun device to our
773 * Guest. */ 783 * Guest. */
774static void net_input(struct virtqueue *vq) 784static void net_input(struct virtqueue *vq)
@@ -781,10 +791,15 @@ static void net_input(struct virtqueue *vq)
781 head = wait_for_vq_desc(vq, iov, &out, &in); 791 head = wait_for_vq_desc(vq, iov, &out, &in);
782 if (out) 792 if (out)
783 errx(1, "Output buffers in net input queue?"); 793 errx(1, "Output buffers in net input queue?");
794
795 /* Deliver interrupt now, since we're about to sleep. */
796 if (vq->pending_used && will_block(net_info->tunfd))
797 trigger_irq(vq);
798
784 len = readv(net_info->tunfd, iov, in); 799 len = readv(net_info->tunfd, iov, in);
785 if (len <= 0) 800 if (len <= 0)
786 err(1, "Failed to read from tun."); 801 err(1, "Failed to read from tun.");
787 add_used_and_trigger(vq, head, len); 802 add_used(vq, head, len);
788} 803}
789 804
790/* This is the helper to create threads. */ 805/* This is the helper to create threads. */