mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 01:49:36 +00:00
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>
This commit is contained in:
parent
95c517c09b
commit
4a8962e21b
1 changed files with 16 additions and 1 deletions
|
@ -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)
|
||||
|
@ -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. */
|
||||
|
|
Loading…
Reference in a new issue