From 696378af1212312425975d739acb54277616f8c9 Mon Sep 17 00:00:00 2001 From: Bart Van Assche Date: Sat, 12 Sep 2020 07:58:00 -0700 Subject: [PATCH] helper_thread: Increase timer accuracy The helper_thread uses select() to wait for the next event. select() rounds up its timeout argument to 1 / HZ. Increase timer accuracy by using a high-res timer if possible. This patch has been tested by running the following fio command and by verifying that the next_log and msec_to_next_event were always above 100 ms: ./fio --debug=helperthread --bandwidth-log --write_bw_log=log --log_avg_msec=1000 --ioengine=null --name=null --size=1G --rw=randwrite --loops=999999 --runtime=60 Signed-off-by: Bart Van Assche --- configure | 21 +++++++++++++++++++++ helper_thread.c | 40 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) diff --git a/configure b/configure index 3846881c..39a9248d 100755 --- a/configure +++ b/configure @@ -2682,6 +2682,24 @@ else pdb=no fi print_config "Windows PDB generation" "$pdb" + +########################################## +# check for timerfd support +timerfd_create="no" +cat > $TMPC << EOF +#include +#include + +int main(int argc, char **argv) +{ + return timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); +} +EOF +if compile_prog "" "" "timerfd_create"; then + timerfd_create="yes" +fi +print_config "timerfd_create" "$timerfd_create" + ############################################################################# if test "$wordsize" = "64" ; then @@ -2983,6 +3001,9 @@ fi if test "$statx_syscall" = "yes"; then output_sym "CONFIG_HAVE_STATX_SYSCALL" fi +if test "$timerfd_create" = "yes"; then + output_sym "CONFIG_HAVE_TIMERFD_CREATE" +fi if test "$fallthrough" = "yes"; then CFLAGS="$CFLAGS -Wimplicit-fallthrough" fi diff --git a/helper_thread.c b/helper_thread.c index f6cdddb8..2d553654 100644 --- a/helper_thread.c +++ b/helper_thread.c @@ -1,5 +1,8 @@ #include #include +#ifdef CONFIG_HAVE_TIMERFD_CREATE +#include +#endif #ifdef CONFIG_VALGRIND_DEV #include #else @@ -13,6 +16,7 @@ #include "pshared.h" static int sleep_accuracy_ms; +static int timerfd = -1; enum action { A_EXIT = 1, @@ -179,6 +183,7 @@ static uint8_t wait_for_action(int fd, unsigned int timeout_ms) }; fd_set rfds, efds; uint8_t action = 0; + uint64_t exp; int res; res = read_from_pipe(fd, &action, sizeof(action)); @@ -188,7 +193,25 @@ static uint8_t wait_for_action(int fd, unsigned int timeout_ms) FD_SET(fd, &rfds); FD_ZERO(&efds); FD_SET(fd, &efds); - res = select(fd + 1, &rfds, NULL, &efds, &timeout); +#ifdef CONFIG_HAVE_TIMERFD_CREATE + { + /* + * If the timer frequency is 100 Hz, select() will round up + * `timeout` to the next multiple of 1 / 100 Hz = 10 ms. Hence + * use a high-resolution timer if possible to increase + * select() timeout accuracy. + */ + struct itimerspec delta = {}; + + delta.it_value.tv_sec = timeout.tv_sec; + delta.it_value.tv_nsec = timeout.tv_usec * 1000; + res = timerfd_settime(timerfd, 0, &delta, NULL); + assert(res == 0); + FD_SET(timerfd, &rfds); + } +#endif + res = select(max(fd, timerfd) + 1, &rfds, NULL, &efds, + timerfd >= 0 ? NULL : &timeout); if (res < 0) { log_err("fio: select() call in helper thread failed: %s", strerror(errno)); @@ -196,6 +219,10 @@ static uint8_t wait_for_action(int fd, unsigned int timeout_ms) } if (FD_ISSET(fd, &rfds)) read_from_pipe(fd, &action, sizeof(action)); + if (timerfd >= 0 && FD_ISSET(timerfd, &rfds)) { + res = read(timerfd, &exp, sizeof(exp)); + assert(res == sizeof(exp)); + } return action; } @@ -272,6 +299,12 @@ static void *helper_thread_main(void *data) assert(clk_tck > 0); sleep_accuracy_ms = (1000 + clk_tck - 1) / clk_tck; +#ifdef CONFIG_HAVE_TIMERFD_CREATE + timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK); + assert(timerfd >= 0); + sleep_accuracy_ms = 1; +#endif + sk_out_assign(hd->sk_out); /* Let another thread handle signals. */ @@ -317,6 +350,11 @@ static void *helper_thread_main(void *data) print_thread_status(); } + if (timerfd >= 0) { + close(timerfd); + timerfd = -1; + } + fio_writeout_logs(false); sk_out_drop(); -- 2.25.1