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
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
49
src/net.c
49
src/net.c
@ -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);
|
||||
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user