Andy Malakov software blog

Thursday, May 13, 2010

Measuring nanoseconds in Java / Windows

I was under false impression that interval timers in Java allow sub-millisecond precision on Windows. I knew that Thread.sleep(millis, nanos) internally uses milliseconds, but for some reason I thought that methods like LockSupport.parkNanos() method provide precise waits. Well, I was wrong. The smallest delay this method can realize is approximately 1.95 milliseconds on my Windows PC.



Back in 2006 David Holmes explained that Java timer intervals are based on waitForMultipleObjects() Windows API (which uses dwMilliseconds). They still are.



One simple (but not universal) workaround is a "spin-sleep":


private static void sleepNanos (long nanoDelay) {
final long end = System.nanoTime() + nanoDelay;
do {
Thread.yield(); // Thread.sleep (0);
} while (System.nanoTime() < end);
}


When running standalone this method consumes all free resources of single CPU core, but it will share with other threads that may be running. For large durations it can be enhanced to use Thread.sleep() for bulk of the waiting.



P.S. Difference between Thread.yield() and Thread.sleep( 0 ) is explained here.