1
1

Added "burst mode" to send a bunch of packets in a row without

intervening select() calls.  This increases performance quite a bit.
Этот коммит содержится в:
Jef Poskanzer 2013-02-22 15:54:05 -08:00
родитель 231c56296e
Коммит 43929b3698
5 изменённых файлов: 101 добавлений и 103 удалений

Просмотреть файл

@ -595,19 +595,33 @@ iperf_parse_arguments(struct iperf_test *test, int argc, char **argv)
int
iperf_send(struct iperf_test *test, fd_set *write_setP)
{
iperf_size_t bytes_sent;
struct iperf_stream *sp;
int burst, r;
register struct iperf_stream *sp;
SLIST_FOREACH(sp, &test->streams, streams) {
if (FD_ISSET(sp->socket, write_setP)) {
if ((bytes_sent = sp->snd(sp)) < 0) {
i_errno = IESTREAMWRITE;
return -1;
/* Can we do burst mode? */
if (test->protocol->id == Pudp && test->settings->rate != 0)
burst = 1; /* nope */
else
burst = 20; /* arbitrary */
for (; burst > 0; --burst) {
SLIST_FOREACH(sp, &test->streams, streams) {
if (FD_ISSET(sp->socket, write_setP)) {
if ((r = sp->snd(sp)) < 0) {
if (r == NET_SOFTERROR)
break;
i_errno = IESTREAMWRITE;
return r;
}
test->bytes_sent += r;
if (burst > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
break;
}
test->bytes_sent += bytes_sent;
FD_CLR(sp->socket, write_setP);
}
}
SLIST_FOREACH(sp, &test->streams, streams)
if (FD_ISSET(sp->socket, write_setP))
FD_CLR(sp->socket, write_setP);
return 0;
}
@ -615,16 +629,16 @@ iperf_send(struct iperf_test *test, fd_set *write_setP)
int
iperf_recv(struct iperf_test *test, fd_set *read_setP)
{
iperf_size_t bytes_sent;
int r;
struct iperf_stream *sp;
SLIST_FOREACH(sp, &test->streams, streams) {
if (FD_ISSET(sp->socket, read_setP)) {
if ((bytes_sent = sp->rcv(sp)) < 0) {
if ((r = sp->rcv(sp)) < 0) {
i_errno = IESTREAMREAD;
return -1;
return r;
}
test->bytes_sent += bytes_sent;
test->bytes_sent += r;
FD_CLR(sp->socket, read_setP);
}
}

Просмотреть файл

@ -33,19 +33,17 @@
int
iperf_tcp_recv(struct iperf_stream *sp)
{
int result = 0;
int size = sp->settings->blksize;
int r;
result = Nread(sp->socket, sp->buffer, size, Ptcp);
r = Nread(sp->socket, sp->buffer, sp->settings->blksize, Ptcp);
if (result < 0) {
return -1;
}
if (r < 0)
return r;
sp->result->bytes_received += result;
sp->result->bytes_received_this_interval += result;
sp->result->bytes_received += r;
sp->result->bytes_received_this_interval += r;
return result;
return r;
}
@ -56,19 +54,17 @@ iperf_tcp_recv(struct iperf_stream *sp)
int
iperf_tcp_send(struct iperf_stream *sp)
{
int result;
int size = sp->settings->blksize;
int r;
result = Nwrite(sp->socket, sp->buffer, size, Ptcp);
r = Nwrite(sp->socket, sp->buffer, sp->settings->blksize, Ptcp);
if (result < 0) {
return -1;
}
if (r < 0)
return r;
sp->result->bytes_sent += result;
sp->result->bytes_sent_this_interval += result;
sp->result->bytes_sent += r;
sp->result->bytes_sent_this_interval += r;
return result;
return r;
}

Просмотреть файл

@ -35,20 +35,19 @@
int
iperf_udp_recv(struct iperf_stream *sp)
{
int result;
int r;
int size = sp->settings->blksize;
int sec, usec, pcount;
double transit = 0, d = 0;
struct timeval sent_time, arrival_time;
result = Nread(sp->socket, sp->buffer, size, Pudp);
r = Nread(sp->socket, sp->buffer, size, Pudp);
if (result < 0) {
return -1;
}
if (r < 0)
return r;
sp->result->bytes_received += result;
sp->result->bytes_received_this_interval += result;
sp->result->bytes_received += r;
sp->result->bytes_received_this_interval += r;
memcpy(&sec, sp->buffer, sizeof(sec));
memcpy(&usec, sp->buffer+4, sizeof(usec));
@ -82,7 +81,7 @@ iperf_udp_recv(struct iperf_stream *sp)
// J = |(R1 - S1) - (R0 - S0)| [/ number of packets, for average]
sp->jitter += (d - sp->jitter) / 16.0;
return result;
return r;
}
@ -107,7 +106,7 @@ send_timer_proc(TimerClientData client_data, struct timeval* nowP)
int
iperf_udp_send(struct iperf_stream *sp)
{
ssize_t result = 0;
int r;
int64_t dtargus;
int64_t adjustus;
uint64_t sec, usec, pcount;
@ -115,46 +114,47 @@ iperf_udp_send(struct iperf_stream *sp)
struct timeval before, after;
TimerClientData cd;
if (sp->udp_green_light) {
gettimeofday(&before, 0);
if (! sp->udp_green_light)
return 0;
++sp->packet_count;
sec = htonl(before.tv_sec);
usec = htonl(before.tv_usec);
pcount = htonl(sp->packet_count);
gettimeofday(&before, 0);
memcpy(sp->buffer, &sec, sizeof(sec));
memcpy(sp->buffer+4, &usec, sizeof(usec));
memcpy(sp->buffer+8, &pcount, sizeof(pcount));
++sp->packet_count;
sec = htonl(before.tv_sec);
usec = htonl(before.tv_usec);
pcount = htonl(sp->packet_count);
result = Nwrite(sp->socket, sp->buffer, size, Pudp);
memcpy(sp->buffer, &sec, sizeof(sec));
memcpy(sp->buffer+4, &usec, sizeof(usec));
memcpy(sp->buffer+8, &pcount, sizeof(pcount));
if (result < 0)
return -1;
r = Nwrite(sp->socket, sp->buffer, size, Pudp);
sp->result->bytes_sent += result;
sp->result->bytes_sent_this_interval += result;
if (r < 0)
return r;
if (sp->settings->rate != 0) {
gettimeofday(&after, 0);
dtargus = (int64_t) (sp->settings->blksize) * SEC_TO_US * 8;
dtargus /= sp->settings->rate;
assert(dtargus != 0);
adjustus = dtargus;
adjustus += (before.tv_sec - after.tv_sec) * SEC_TO_US;
adjustus += (before.tv_usec - after.tv_usec);
if (adjustus > 0) {
dtargus = adjustus;
}
cd.p = sp;
sp->udp_green_light = 0;
sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, dtargus, 0);
if (sp->send_timer == NULL)
return -1;
sp->result->bytes_sent += r;
sp->result->bytes_sent_this_interval += r;
if (sp->settings->rate != 0) {
gettimeofday(&after, 0);
dtargus = (int64_t) (sp->settings->blksize) * SEC_TO_US * 8;
dtargus /= sp->settings->rate;
assert(dtargus != 0);
adjustus = dtargus;
adjustus += (before.tv_sec - after.tv_sec) * SEC_TO_US;
adjustus += (before.tv_usec - after.tv_usec);
if (adjustus > 0) {
dtargus = adjustus;
}
cd.p = sp;
sp->udp_green_light = 0;
sp->send_timer = tmr_create((struct timeval*) 0, send_timer_proc, cd, dtargus, 0);
if (sp->send_timer == NULL)
return -1;
}
return result;
return r;
}

Просмотреть файл

@ -131,7 +131,7 @@ Nread(int fd, void *buf, int count, int prot)
if (errno == EINTR)
n = 0;
else
return -1;
return NET_HARDERROR;
} else if (n == 0)
break;
@ -144,9 +144,6 @@ Nread(int fd, void *buf, int count, int prot)
/*
* N W R I T E
*
* XXX: After updating this function to use read/write, the only difference between
* TCP and UDP is that udp handles ENOBUFS. Should we merge the two?
*/
int
@ -155,34 +152,22 @@ Nwrite(int fd, void *buf, int count, int prot)
register int n;
register int nleft = count;
if (prot == SOCK_DGRAM) { /* UDP mode */
while (nleft > 0) {
if ((n = write(fd, buf, nleft)) < 0) {
if (errno == EINTR) {
n = 0;
} else if (errno == ENOBUFS) {
/* wait if run out of buffers */
/* XXX: but how long to wait? Start shorter and increase delay each time?? */
delay(18000); // XXX: Fixme!
n = 0;
} else {
return -1;
}
}
nleft -= n;
buf += n;
}
} else {
while (nleft > 0) {
if ((n = write(fd, buf, nleft)) < 0) {
if (errno == EINTR)
n = 0;
else
return -1;
}
nleft -= n;
buf += n;
}
while (nleft > 0) {
if ((n = write(fd, buf, nleft)) < 0) {
switch (errno) {
case EINTR:
return count - nleft;
case EAGAIN:
case ENOBUFS:
return NET_SOFTERROR;
default:
return NET_HARDERROR;
}
}
nleft -= n;
buf += n;
}
return count;
}

Просмотреть файл

@ -18,6 +18,9 @@ int getsock_tcp_mss(int);
int set_tcp_options(int, int, int);
int setnonblocking(int);
#define NET_SOFTERROR -1
#define NET_HARDERROR -2
unsigned long long htonll(unsigned long long);
unsigned long long ntohll(unsigned long long);