Skip to content

Commit

Permalink
lguest: try to batch interrupts on network receive
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Rusty Russell committed Jun 12, 2009
1 parent 95c517c commit 4a8962e
Showing 1 changed file with 16 additions and 1 deletion.
17 changes: 16 additions & 1 deletion Documentation/lguest/lguest.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,16 @@ static void net_output(struct virtqueue *vq)
add_used(vq, head, 0);
}

/* Will reading from this file descriptor block? */
static bool will_block(int fd)
{
fd_set fdset;
struct timeval zero = { 0, 0 };
FD_ZERO(&fdset);
FD_SET(fd, &fdset);
return select(fd+1, &fdset, NULL, NULL, &zero) != 1;
}

/* This is where we handle packets coming in from the tun device to our
* Guest. */
static void net_input(struct virtqueue *vq)
Expand All @@ -781,10 +791,15 @@ static void net_input(struct virtqueue *vq)
head = wait_for_vq_desc(vq, iov, &out, &in);
if (out)
errx(1, "Output buffers in net input queue?");

/* Deliver interrupt now, since we're about to sleep. */
if (vq->pending_used && will_block(net_info->tunfd))
trigger_irq(vq);

len = readv(net_info->tunfd, iov, in);
if (len <= 0)
err(1, "Failed to read from tun.");
add_used_and_trigger(vq, head, len);
add_used(vq, head, len);
}

/* This is the helper to create threads. */
Expand Down

0 comments on commit 4a8962e

Please sign in to comment.