Skip to content

Commit 7dcd667

Browse files
committed
Performance: use MSG_DONTWAIT instead of select.
This also improves a bit the conversion from nanoseconds to seconds + microseconds.
1 parent f689c31 commit 7dcd667

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ Next
55

66
## Bugfixes and other changes
77

8-
- ci: Removing travis-ci (#446, thanks @gsnw-sebast)
8+
- ci: Removed travis-ci (#446, thanks @gsnw-sebast)
9+
- Performance optimization: reduce number of select calls and use
10+
recvmsg with MSG_DONTWAIT instead (#449)
911

1012
fping 5.5 (2025-12-31)
1113
======================

configure.ac

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,9 @@ AH_BOTTOM([
129129
dnl Checks for header files.
130130
AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h])
131131

132+
AC_CHECK_DECL([MSG_DONTWAIT], [AC_DEFINE(HAVE_MSG_DONTWAIT, [1], [MSG_DONTWAIT is defined])], [], [#include <sys/types.h>
133+
#include <sys/socket.h>])
134+
132135
AC_CONFIG_FILES([Makefile
133136
doc/Makefile
134137
src/Makefile])

src/fping.c

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,24 +2806,36 @@ int receive_packet(int64_t wait_time,
28062806
struct cmsghdr *cmsg;
28072807

28082808
/* Wait for a socket to become ready */
2809-
if (wait_time) {
2810-
to.tv_sec = wait_time / UINT64_C(1000000000);
2811-
to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1;
2812-
}
2813-
else {
2814-
to.tv_sec = 0;
2815-
to.tv_usec = 0;
2816-
}
2817-
s = socket_can_read(&to);
2818-
if (s == -1) {
2819-
return 0; /* timeout */
2809+
#if HAVE_MSG_DONTWAIT
2810+
if (wait_time == 0) {
2811+
/* Optimization: if wait_time is 0, we can skip select() and just try to
2812+
* read from the sockets with MSG_DONTWAIT */
2813+
recv_len = (socket4 >= 0) ? recvmsg(socket4, &recv_msghdr, MSG_TRUNC | MSG_DONTWAIT) : -1;
2814+
#ifdef IPV6
2815+
if (recv_len <= 0 && socket6 >= 0) {
2816+
/* Reset fields potentially modified by failed recvmsg */
2817+
recv_msghdr.msg_namelen = reply_src_addr_len;
2818+
recv_msghdr.msg_controllen = sizeof(msg_control);
2819+
recv_len = recvmsg(socket6, &recv_msghdr, MSG_TRUNC | MSG_DONTWAIT);
2820+
}
2821+
#endif
2822+
if (recv_len > 0) {
2823+
goto packet_received;
2824+
}
2825+
return 0;
28202826
}
2827+
#endif
2828+
2829+
int64_t wait_us = (wait_time + 999) / 1000; // round up (1 ns -> 1 us)
2830+
to.tv_sec = wait_us / 1000000;
2831+
to.tv_usec = wait_us % 1000000;
28212832

2822-
recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC);
2823-
if (recv_len <= 0) {
2833+
s = socket_can_read(&to);
2834+
if (s == -1 || (recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC)) <= 0) {
28242835
return 0;
28252836
}
28262837

2838+
packet_received:
28272839
/* ancilliary data */
28282840
{
28292841
#if HAVE_SO_TIMESTAMPNS

0 commit comments

Comments
 (0)