Added "burst mode" to send a bunch of packets in a row without
intervening select() calls. This increases performance quite a bit.
Этот коммит содержится в:
родитель
231c56296e
Коммит
43929b3698
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
37
src/net.c
37
src/net.c
@ -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);
|
||||||
|
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user