From: David Schweikert Date: Fri, 2 Jan 2026 07:49:06 +0000 (+0100) Subject: Performance: use MSG_DONTWAIT instead of select. X-Git-Url: https://git.gsnw.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7dcd667e4c1843346cde45ac964242107910f9b4;p=fping.git Performance: use MSG_DONTWAIT instead of select. This also improves a bit the conversion from nanoseconds to seconds + microseconds. --- diff --git a/CHANGELOG.md b/CHANGELOG.md index 877b703..d83086d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,9 @@ Next ## Bugfixes and other changes -- ci: Removing travis-ci (#446, thanks @gsnw-sebast) +- ci: Removed travis-ci (#446, thanks @gsnw-sebast) +- Performance optimization: reduce number of select calls and use + recvmsg with MSG_DONTWAIT instead (#449) fping 5.5 (2025-12-31) ====================== diff --git a/configure.ac b/configure.ac index b2b7f1b..115f906 100644 --- a/configure.ac +++ b/configure.ac @@ -129,6 +129,9 @@ AH_BOTTOM([ dnl Checks for header files. AC_CHECK_HEADERS([unistd.h sys/file.h stdlib.h sys/select.h]) +AC_CHECK_DECL([MSG_DONTWAIT], [AC_DEFINE(HAVE_MSG_DONTWAIT, [1], [MSG_DONTWAIT is defined])], [], [#include +#include ]) + AC_CONFIG_FILES([Makefile doc/Makefile src/Makefile]) diff --git a/src/fping.c b/src/fping.c index ecba673..ada5255 100644 --- a/src/fping.c +++ b/src/fping.c @@ -2806,24 +2806,36 @@ int receive_packet(int64_t wait_time, struct cmsghdr *cmsg; /* Wait for a socket to become ready */ - if (wait_time) { - to.tv_sec = wait_time / UINT64_C(1000000000); - to.tv_usec = (wait_time % UINT64_C(1000000000)) / 1000 + 1; - } - else { - to.tv_sec = 0; - to.tv_usec = 0; - } - s = socket_can_read(&to); - if (s == -1) { - return 0; /* timeout */ +#if HAVE_MSG_DONTWAIT + if (wait_time == 0) { + /* Optimization: if wait_time is 0, we can skip select() and just try to + * read from the sockets with MSG_DONTWAIT */ + recv_len = (socket4 >= 0) ? recvmsg(socket4, &recv_msghdr, MSG_TRUNC | MSG_DONTWAIT) : -1; +#ifdef IPV6 + if (recv_len <= 0 && socket6 >= 0) { + /* Reset fields potentially modified by failed recvmsg */ + recv_msghdr.msg_namelen = reply_src_addr_len; + recv_msghdr.msg_controllen = sizeof(msg_control); + recv_len = recvmsg(socket6, &recv_msghdr, MSG_TRUNC | MSG_DONTWAIT); + } +#endif + if (recv_len > 0) { + goto packet_received; + } + return 0; } +#endif + + int64_t wait_us = (wait_time + 999) / 1000; // round up (1 ns -> 1 us) + to.tv_sec = wait_us / 1000000; + to.tv_usec = wait_us % 1000000; - recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC); - if (recv_len <= 0) { + s = socket_can_read(&to); + if (s == -1 || (recv_len = recvmsg(s, &recv_msghdr, MSG_TRUNC)) <= 0) { return 0; } +packet_received: /* ancilliary data */ { #if HAVE_SO_TIMESTAMPNS