File 2481-win32-Use-QPC-timer-on-Windows.patch of Package erlang
From cd9c87d64dec190639c459de4added891ef330d4 Mon Sep 17 00:00:00 2001
From: Dan Gudmundsson <dgud@erlang.org>
Date: Tue, 4 Aug 2020 14:55:06 +0200
Subject: [PATCH 1/2] win32: Use QPC timer on Windows
If resolution is good enough use QueryPerformanceTimer on windows,
which with thread compensation gives an ~0.1ms resolution instead of 15ms.
The cost is ~30% higher for qpc than for GetTickCound64
and the thread compensation cost adds another 0.5% amortized cost.
---
erts/emulator/sys/win32/sys_time.c | 31 ++++++++++++++++--------------
1 file changed, 17 insertions(+), 14 deletions(-)
diff --git a/erts/emulator/sys/win32/sys_time.c b/erts/emulator/sys/win32/sys_time.c
index a1dd14f871..a14b9dd2c0 100644
--- a/erts/emulator/sys/win32/sys_time.c
+++ b/erts/emulator/sys/win32/sys_time.c
@@ -141,15 +141,27 @@ SystemTime2MilliSec(SYSTEMTIME *stp)
return stime;
}
+#define SKIP 0x3FF
+
static ErtsMonotonicTime
os_monotonic_time_qpc(void)
{
LARGE_INTEGER pc;
- if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc))
- erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
+ ErtsMonotonicTime temp;
- return (ErtsMonotonicTime) pc.QuadPart;
+ /*
+ * Windows QPC does not ensure that the returned clocks
+ * are monotonic over several threads, reduce resolution to ensure
+ * that we return monotonic clocks even on multiple threads.
+ */
+ do {
+ if (!(*internal_state.r.o.pQueryPerformanceCounter)(&pc))
+ erts_exit(ERTS_ABORT_EXIT, "QueryPerformanceCounter() failed\n");
+ temp = (ErtsMonotonicTime) pc.QuadPart;
+ } while(!(temp & SKIP));
+
+ return temp & (0xFFFFFFFFFFFFFFFF-SKIP);
}
static void
@@ -365,18 +377,9 @@ sys_init_time(ErtsSysInitTimeResult *init_resp)
internal_state.r.o.pcf = (Uint32) pf.QuadPart;
sys_hrtime_func = sys_hrtime_qpc;
-
- /*
- * We only use QueryPerformanceCounter() for
- * os-monotonic-time if its frequency is equal
- * to, or larger than GHz in order to ensure
- * that the user wont be able to observe faulty
- * order between values retrieved on different threads.
- */
- if (pf.QuadPart < (LONGLONG) 1000*1000*1000)
- goto get_tick_count64;
- if (ERTS_DISABLE_USE_OF_QPC_FOR_MONOTONIC_TIME)
+ /* We need at least 0.1 microseconds resolution */
+ if (pf.QuadPart < (LONGLONG) 9*1000*1000)
goto get_tick_count64;
init_resp->os_monotonic_time_info.func = "QueryPerformanceCounter";
--
2.26.2