Skip to content

UDPSOCKET_ECHOTEST_NONBLOCK performance improvement. #10776

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 18, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 35 additions & 55 deletions TESTS/netsocket/udp/udpsocket_echotest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,12 @@ namespace {
static const int SIGNAL_SIGIO_RX = 0x1;
static const int SIGNAL_SIGIO_TX = 0x2;
static const int SIGIO_TIMEOUT = 5000; //[ms]
static const int WAIT2RECV_TIMEOUT = 5000; //[ms]
static const int RETRIES = 2;

static const double EXPECTED_LOSS_RATIO = 0.0;
static const double TOLERATED_LOSS_RATIO = 0.3;

UDPSocket sock;
Semaphore tx_sem(0, 1);
UDPSocket *sock;
EventFlags signals;

static const int BUFF_SIZE = 1200;
Expand Down Expand Up @@ -110,33 +108,6 @@ void UDPSOCKET_ECHOTEST()
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
}

void udpsocket_echotest_nonblock_receiver(void *receive_bytes)
{
int expt2recv = *(int *)receive_bytes;
int recvd;
for (int retry_cnt = 0; retry_cnt <= RETRIES; retry_cnt++) {
recvd = sock.recvfrom(NULL, rx_buffer, expt2recv);
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
if (tc_exec_time.read() >= time_allotted) {
break;
}
signals.wait_all(SIGNAL_SIGIO_RX, WAIT2RECV_TIMEOUT);
--retry_cnt;
continue;
} else if (recvd < 0) {
printf("sock.recvfrom returned %d\n", recvd);
TEST_FAIL();
break;
} else if (recvd == expt2recv) {
break;
}
}

drop_bad_packets(sock, 0); // timeout equivalent to set_blocking(false)

tx_sem.release();
}

void UDPSOCKET_ECHOTEST_NONBLOCK()
{
tc_exec_time.start();
Expand All @@ -145,58 +116,66 @@ void UDPSOCKET_ECHOTEST_NONBLOCK()
SocketAddress udp_addr;
NetworkInterface::get_default_instance()->gethostbyname(ECHO_SERVER_ADDR, &udp_addr);
udp_addr.set_port(ECHO_SERVER_PORT);

TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.open(NetworkInterface::get_default_instance()));
sock.set_blocking(false);
sock.sigio(callback(_sigio_handler));

sock = new UDPSocket();
if (sock == NULL) {
TEST_FAIL_MESSAGE("UDPSocket not created");
return;
}
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock->open(NetworkInterface::get_default_instance()));
sock->set_blocking(false);
sock->sigio(callback(_sigio_handler));
int sent;
int packets_sent = 0;
int packets_recv = 0;
Thread *thread;
unsigned char *stack_mem = (unsigned char *)malloc(OS_STACK_SIZE);
TEST_ASSERT_NOT_NULL(stack_mem);

for (int s_idx = 0; s_idx < sizeof(pkt_sizes) / sizeof(*pkt_sizes); ++s_idx) {
int pkt_s = pkt_sizes[s_idx];
int packets_sent_prev = packets_sent;

thread = new Thread(osPriorityNormal,
OS_STACK_SIZE,
stack_mem,
"receiver");
TEST_ASSERT_EQUAL(osOK, thread->start(callback(udpsocket_echotest_nonblock_receiver, &pkt_s)));

for (int retry_cnt = 0; retry_cnt <= RETRIES; retry_cnt++) {
fill_tx_buffer_ascii(tx_buffer, pkt_s);

sent = sock.sendto(udp_addr, tx_buffer, pkt_s);
sent = sock->sendto(udp_addr, tx_buffer, pkt_s);
if (sent == pkt_s) {
packets_sent++;
} else if (sent == NSAPI_ERROR_WOULD_BLOCK) {
if (tc_exec_time.read() >= time_allotted ||
osSignalWait(SIGNAL_SIGIO_TX, SIGIO_TIMEOUT).status == osEventTimeout) {
signals.wait_all(SIGNAL_SIGIO_TX, SIGIO_TIMEOUT) == osFlagsErrorTimeout) {
continue;
}
--retry_cnt;
} else {
printf("[Round#%02d - Sender] error, returned %d\n", s_idx, sent);
continue;
}
if (!tx_sem.try_acquire_for(WAIT2RECV_TIMEOUT * 2)) { // RX might wait up to WAIT2RECV_TIMEOUT before recvfrom
continue;

int recvd;
for (int retry_recv = 0; retry_recv <= RETRIES; retry_recv++) {
recvd = sock->recvfrom(NULL, rx_buffer, pkt_s);
if (recvd == NSAPI_ERROR_WOULD_BLOCK) {
if (tc_exec_time.read() >= time_allotted) {
break;
}
signals.wait_all(SIGNAL_SIGIO_RX, SIGIO_TIMEOUT);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous loop uses osSignalWait(SIGNAL_SIGIO_TX, SIGIO_TIMEOUT).status == osEventTimeout) which will wait that signal send to current thread.
However, I don't see anyone sending that signal.

The _sigio_handler() seems to set flags only on this EventFlags signals variable.

Please fix the previous loop to use the same eventflag variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed

--retry_recv;
continue;
} else if (recvd < 0) {
printf("sock.recvfrom returned %d\n", recvd);
TEST_FAIL();
break;
} else if (recvd == pkt_s) {
break;
}
}

if (recvd == pkt_s) {
break;
}
break;
}
// Make sure that at least one packet of every size was sent.
TEST_ASSERT_TRUE(packets_sent > packets_sent_prev);
thread->join();
delete thread;
if (memcmp(tx_buffer, rx_buffer, pkt_s) == 0) {
packets_recv++;
}
}
free(stack_mem);

// Packet loss up to 30% tolerated
if (packets_sent > 0) {
Expand All @@ -220,6 +199,7 @@ void UDPSOCKET_ECHOTEST_NONBLOCK()

#endif
}
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock.close());
TEST_ASSERT_EQUAL(NSAPI_ERROR_OK, sock->close());
delete sock;
tc_exec_time.stop();
}