Mark Clowes (~39M 🇬🇧)
Index - Windows Subsystem for Linux 2 has an unreliable clock
2025-07-19For many years I have used Cygwin when I wanted unix tools in Win32. All your favourites are compiled as exe's with a DLL providing some API functions. I was pleased to see Microsoft Windows now including Windows Subsystem for Linux and hoped it would be a useful alternative. One of my occasional use cases involves precise (by my requirements) timing using sleep
and WSL2 is perplexingly unreliable. I ran tests sleep
ing for 100, 1000, and 3600 seconds on Cygwin (which will be counting in the native OS), WSL (which is virtualised Linux subsystem) and an Ubuntu VM on Hyper-V.
WSL: % (date +"%s.%N," && sleep 100s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749133618.073570894, 1749133726.196575192, 108.123 % (date +"%s.%N," && sleep 1000s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749134165.895252116, 1749135255.416774283, 1089.52 % (date +"%s.%N," && sleep 3600s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749134268.424014751, 1749138187.680189410, 3919.26 Cygwin: $ (date +"%s.%N," && sleep 100s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749133508.645041600, 1749133608.689973900, 100.045 $ (date +"%s.%N," && sleep 1000s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749134177.811352300, 1749135177.844886000, 1000.03 $ (date +"%s.%N," && sleep 3600s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749134200.262718600, 1749137800.315200600, 3600.05 Ubuntu on Hyper-V: % (date +"%s.%N," && sleep 100s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749539473.191445112, 1749539573.196320349, 100.005 % (date +"%s.%N," && sleep 1000s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749539978.954144654, 1749540978.957940659, 1000.004 % (date +"%s.%N," && sleep 3600s && date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' 1749541095.007499988, 1749544695.011120224, 3600.004
So asking WSL to sleep
for 100 seconds will actually return after 108 seconds. This is a systemic error of about 8% for all sleep periods. Ubuntu on Hyper-V does not exhibit this problem despite presumably being virtualised in a similiar way.
I ran this command in cygwin to sample the skew between the system clock and WSL's clock 10 times a second:
while :; do (date +"%s.%N," && wsl date +"%s.%N,") | paste -s -d ' ' | awk '{ $3 = $2 - $1 } 1' >> skew.csv ; sleep 0.1s ; done
Charting the data shows that WSL's clock linearly falls behind the system clock until the Hypervisor jumps the clock forward to compensate every 10 seconds or so. Presumably this is a hack to fix Github.com: WSL2 clock becomes unsynced on Desktop system · Issue #7255 · microsoft/WSL.