While running the following benchmark on Java 11 (Linux and MacOS):
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class ThreadSleepVsParkNanosBenchmark {
@Benchmark
public void sleep1ms() throws Exception {
Thread.sleep(1);
}
@Benchmark
public void parkNanos1ms() {
LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1));
}
@Benchmark
public void parkNanos500us() {
LockSupport.parkNanos(TimeUnit.MICROSECONDS.toNanos(500));
}
@Benchmark
public void parkNanos100us() {
LockSupport.parkNanos(TimeUnit.MICROSECONDS.toNanos(100));
}
}
I've found out that the costs of running Thread.sleep(1) and LockSupport.parkNanos(TimeUnit.MILLISECONDS.toNanos(1)) i.e. the overhead of suspending and revoking the thread are pretty much the same on both platforms. But the overhead of LockSupport.parkNanos(TimeUnit.MICROSECONDS.toNanos(100)) is significantly lower:
Linux
Benchmark Mode Cnt Score Error Units
ThreadSleepVsParkNanosBenchmark.parkNanos100us avgt 100 159.775 ± 0.248 us/op
ThreadSleepVsParkNanosBenchmark.parkNanos500us avgt 100 612.971 ± 0.578 us/op
ThreadSleepVsParkNanosBenchmark.parkNanos1ms avgt 100 1103.372 ± 4.685 us/op
ThreadSleepVsParkNanosBenchmark.sleep1ms avgt 100 1119.566 ± 0.940 us/op
MacOS
ThreadSleepVsParkNanosBenchmark.parkNanos100us avgt 100 156,696 ± 6,977 us/op
ThreadSleepVsParkNanosBenchmark.parkNanos500us avgt 100 752,520 ± 23,203 us/op
ThreadSleepVsParkNanosBenchmark.parkNanos1ms avgt 100 1508,832 ± 7,580 us/op
ThreadSleepVsParkNanosBenchmark.sleep1ms avgt 100 1430,396 ± 32,876 us/op
What is the explanation? As far as it comes from the JavaDoc both Thread.sleep() and LockSupport.parkNanos() put the thread into Thread.State.TIMED_WAITING, so the mechanism under the hood must be the same along with the costs.