From: Brandon Paupore Date: Tue, 12 Oct 2021 19:00:41 +0000 (-0500) Subject: Query Windows clock frequency and use reported max X-Git-Tag: fio-3.29~69^2 X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=3d0d549ab34f64d19a4ee0a0ffdd4f79ebba48ec;p=fio.git Query Windows clock frequency and use reported max Previously FIO used the Windows lower-bound clock frequency of 64 Hz for its helper-thread. This caused IOPS/BW logs to have large drift between timestamps when not using per-unit logging for those measurements. Now query the current resolution and set to use the maximum for more accurate timestamps. Note that the resolution is automatically restored after FIO terminates. Signed-off-by: Brandon Paupore --- diff --git a/Makefile b/Makefile index 5198f70e..c3feb53f 100644 --- a/Makefile +++ b/Makefile @@ -275,8 +275,8 @@ ifeq ($(CONFIG_TARGET_OS), Darwin) LIBS += -lpthread -ldl endif ifneq (,$(findstring CYGWIN,$(CONFIG_TARGET_OS))) - SOURCE += os/windows/cpu-affinity.c os/windows/posix.c - WINDOWS_OBJS = os/windows/cpu-affinity.o os/windows/posix.o lib/hweight.o + SOURCE += os/windows/cpu-affinity.c os/windows/posix.c os/windows/dlls.c + WINDOWS_OBJS = os/windows/cpu-affinity.o os/windows/posix.o os/windows/dlls.o lib/hweight.o LIBS += -lpthread -lpsapi -lws2_32 -lssp FIO_CFLAGS += -DPSAPI_VERSION=1 -Ios/windows/posix/include -Wno-format endif diff --git a/helper_thread.c b/helper_thread.c index d8e7ebfe..b9b83db3 100644 --- a/helper_thread.c +++ b/helper_thread.c @@ -9,6 +9,10 @@ #define DRD_IGNORE_VAR(x) do { } while (0) #endif +#ifdef WIN32 +#include "os/os-windows.h" +#endif + #include "fio.h" #include "smalloc.h" #include "helper_thread.h" @@ -283,19 +287,12 @@ static void *helper_thread_main(void *data) } }; struct timespec ts; - int clk_tck, ret = 0; + long clk_tck; + int ret = 0; -#ifdef _SC_CLK_TCK - clk_tck = sysconf(_SC_CLK_TCK); -#else - /* - * The timer frequence is variable on Windows. Instead of trying to - * query it, use 64 Hz, the clock frequency lower bound. See also - * https://carpediemsystems.co.uk/2019/07/18/windows-system-timer-granularity/. - */ - clk_tck = 64; -#endif - dprint(FD_HELPERTHREAD, "clk_tck = %d\n", clk_tck); + os_clk_tck(&clk_tck); + + dprint(FD_HELPERTHREAD, "clk_tck = %ld\n", clk_tck); assert(clk_tck > 0); sleep_accuracy_ms = (1000 + clk_tck - 1) / clk_tck; diff --git a/os/os.h b/os/os.h index 827b61e9..5965d7b8 100644 --- a/os/os.h +++ b/os/os.h @@ -412,4 +412,13 @@ static inline bool os_cpu_has(cpu_features feature) # define fio_mkdir(path, mode) mkdir(path, mode) #endif +#ifdef _SC_CLK_TCK +static inline void os_clk_tck(long *clk_tck) +{ + *clk_tck = sysconf(_SC_CLK_TCK); +} +#else +extern void os_clk_tck(long *clk_tck); +#endif + #endif /* FIO_OS_H */ diff --git a/os/windows/dlls.c b/os/windows/dlls.c new file mode 100644 index 00000000..774b1c61 --- /dev/null +++ b/os/windows/dlls.c @@ -0,0 +1,33 @@ +#include "os/os.h" + +#include + +void os_clk_tck(long *clk_tck) +{ + /* + * The timer resolution is variable on Windows. Try to query it + * or use 64 Hz, the clock frequency lower bound. See also + * https://carpediemsystems.co.uk/2019/07/18/windows-system-timer-granularity/. + */ + unsigned long minRes, maxRes, curRes; + HMODULE lib; + FARPROC queryTimer; + FARPROC setTimer; + + if (!(lib = LoadLibrary(TEXT("ntdll.dll"))) || + !(queryTimer = GetProcAddress(lib, "NtQueryTimerResolution")) || + !(setTimer = GetProcAddress(lib, "NtSetTimerResolution"))) { + dprint(FD_HELPERTHREAD, + "Failed to load ntdll library, set to lower bound 64 Hz\n"); + *clk_tck = 64; + } else { + queryTimer(&minRes, &maxRes, &curRes); + dprint(FD_HELPERTHREAD, + "minRes = %lu, maxRes = %lu, curRes = %lu\n", + minRes, maxRes, curRes); + + /* Use maximum resolution for most accurate timestamps */ + setTimer(maxRes, 1, &curRes); + *clk_tck = (long) (10000000L / maxRes); + } +} \ No newline at end of file diff --git a/stat.c b/stat.c index ac53463d..30f9b5c1 100644 --- a/stat.c +++ b/stat.c @@ -17,7 +17,11 @@ #include "zbd.h" #include "oslib/asprintf.h" +#ifdef WIN32 +#define LOG_MSEC_SLACK 2 +#else #define LOG_MSEC_SLACK 1 +#endif struct fio_sem *stat_sem;