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 int
iperf_send(struct iperf_test *test, fd_set *write_setP) iperf_send(struct iperf_test *test, fd_set *write_setP)
{ {
iperf_size_t bytes_sent; int burst, r;
struct iperf_stream *sp; register struct iperf_stream *sp;
/* 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) { SLIST_FOREACH(sp, &test->streams, streams) {
if (FD_ISSET(sp->socket, write_setP)) { if (FD_ISSET(sp->socket, write_setP)) {
if ((bytes_sent = sp->snd(sp)) < 0) { if ((r = sp->snd(sp)) < 0) {
if (r == NET_SOFTERROR)
break;
i_errno = IESTREAMWRITE; i_errno = IESTREAMWRITE;
return -1; return r;
} }
test->bytes_sent += bytes_sent; test->bytes_sent += r;
if (burst > 1 && test->settings->bytes != 0 && test->bytes_sent >= test->settings->bytes)
break;
}
}
}
SLIST_FOREACH(sp, &test->streams, streams)
if (FD_ISSET(sp->socket, write_setP))
FD_CLR(sp->socket, write_setP); FD_CLR(sp->socket, write_setP);
}
}
return 0; return 0;
} }
@ -615,16 +629,16 @@ iperf_send(struct iperf_test *test, fd_set *write_setP)
int int
iperf_recv(struct iperf_test *test, fd_set *read_setP) iperf_recv(struct iperf_test *test, fd_set *read_setP)
{ {
iperf_size_t bytes_sent; int r;
struct iperf_stream *sp; struct iperf_stream *sp;
SLIST_FOREACH(sp, &test->streams, streams) { SLIST_FOREACH(sp, &test->streams, streams) {
if (FD_ISSET(sp->socket, read_setP)) { if (FD_ISSET(sp->socket, read_setP)) {
if ((bytes_sent = sp->rcv(sp)) < 0) { if ((r = sp->rcv(sp)) < 0) {
i_errno = IESTREAMREAD; i_errno = IESTREAMREAD;
return -1; return r;
} }
test->bytes_sent += bytes_sent; test->bytes_sent += r;
FD_CLR(sp->socket, read_setP); FD_CLR(sp->socket, read_setP);
} }
} }

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

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

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

@ -35,20 +35,19 @@
int int
iperf_udp_recv(struct iperf_stream *sp) iperf_udp_recv(struct iperf_stream *sp)
{ {
int result; int r;
int size = sp->settings->blksize; int size = sp->settings->blksize;
int sec, usec, pcount; int sec, usec, pcount;
double transit = 0, d = 0; double transit = 0, d = 0;
struct timeval sent_time, arrival_time; 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) { if (r < 0)
return -1; return r;
}
sp->result->bytes_received += result; sp->result->bytes_received += r;
sp->result->bytes_received_this_interval += result; sp->result->bytes_received_this_interval += r;
memcpy(&sec, sp->buffer, sizeof(sec)); memcpy(&sec, sp->buffer, sizeof(sec));
memcpy(&usec, sp->buffer+4, sizeof(usec)); 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] // J = |(R1 - S1) - (R0 - S0)| [/ number of packets, for average]
sp->jitter += (d - sp->jitter) / 16.0; 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 int
iperf_udp_send(struct iperf_stream *sp) iperf_udp_send(struct iperf_stream *sp)
{ {
ssize_t result = 0; int r;
int64_t dtargus; int64_t dtargus;
int64_t adjustus; int64_t adjustus;
uint64_t sec, usec, pcount; uint64_t sec, usec, pcount;
@ -115,7 +114,9 @@ iperf_udp_send(struct iperf_stream *sp)
struct timeval before, after; struct timeval before, after;
TimerClientData cd; TimerClientData cd;
if (sp->udp_green_light) { if (! sp->udp_green_light)
return 0;
gettimeofday(&before, 0); gettimeofday(&before, 0);
++sp->packet_count; ++sp->packet_count;
@ -127,13 +128,13 @@ iperf_udp_send(struct iperf_stream *sp)
memcpy(sp->buffer+4, &usec, sizeof(usec)); memcpy(sp->buffer+4, &usec, sizeof(usec));
memcpy(sp->buffer+8, &pcount, sizeof(pcount)); memcpy(sp->buffer+8, &pcount, sizeof(pcount));
result = Nwrite(sp->socket, sp->buffer, size, Pudp); r = Nwrite(sp->socket, sp->buffer, size, Pudp);
if (result < 0) if (r < 0)
return -1; return r;
sp->result->bytes_sent += result; sp->result->bytes_sent += r;
sp->result->bytes_sent_this_interval += result; sp->result->bytes_sent_this_interval += r;
if (sp->settings->rate != 0) { if (sp->settings->rate != 0) {
gettimeofday(&after, 0); gettimeofday(&after, 0);
@ -152,9 +153,8 @@ iperf_udp_send(struct iperf_stream *sp)
if (sp->send_timer == NULL) if (sp->send_timer == NULL)
return -1; return -1;
} }
}
return result; return r;
} }

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

@ -131,7 +131,7 @@ Nread(int fd, void *buf, int count, int prot)
if (errno == EINTR) if (errno == EINTR)
n = 0; n = 0;
else else
return -1; return NET_HARDERROR;
} else if (n == 0) } else if (n == 0)
break; break;
@ -144,9 +144,6 @@ Nread(int fd, void *buf, int count, int prot)
/* /*
* N W R I T E * 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 int
@ -155,35 +152,23 @@ Nwrite(int fd, void *buf, int count, int prot)
register int n; register int n;
register int nleft = count; register int nleft = count;
if (prot == SOCK_DGRAM) { /* UDP mode */
while (nleft > 0) { while (nleft > 0) {
if ((n = write(fd, buf, nleft)) < 0) { if ((n = write(fd, buf, nleft)) < 0) {
if (errno == EINTR) { switch (errno) {
n = 0; case EINTR:
} else if (errno == ENOBUFS) { return count - nleft;
/* wait if run out of buffers */
/* XXX: but how long to wait? Start shorter and increase delay each time?? */ case EAGAIN:
delay(18000); // XXX: Fixme! case ENOBUFS:
n = 0; return NET_SOFTERROR;
} else {
return -1; default:
return NET_HARDERROR;
} }
} }
nleft -= n; nleft -= n;
buf += 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;
}
}
return count; return count;
} }

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

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