Skip to content

morphar/powernap

Repository files navigation

Go Reference

powernap

A more precise sleep for Go.

time.Sleep only promises to sleep for at least the duration specified.
The amount of overshooting can be quite large and totally random.
When microsecond precision is needed, powernap can be the solution you need.
Depending on your system, it becomes relatively precise above 1-10 µs.

powernap was created for the cases, where you're willing to give up CPU cycles for precision.

When possible, a safe part of the duration is done with time.Sleep, which probably happens around 1-10 ms, the rest is done by looping until the total duration has elapsed.

WARNING!

powernap can undershoot and makes no promises of sleeping "at least" for the duration given.
The promise is: Spend CPU cycles to get as close as possible to the wanted duration, but be smart about it.

Benchmark

It can be hard to describe the precise effect, so the following benchmark will show you the differences.
You can run this benchmark yourself with go test -bench . The last value ns/op should be as close as possible to the test names, e.g.: 100ns.

Concurrently on 8 cores:

$ go test -run none -bench Sleep
goos: darwin
goarch: amd64
pkg: github.com/morphar/powernap
cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
BenchmarkNativeSleep/1ns-8         	 3668739	       324.8 ns/op
BenchmarkNativeSleep/10ns-8        	 3734082	       320.1 ns/op
BenchmarkNativeSleep/100ns-8       	 3241970	       370.3 ns/op
BenchmarkNativeSleep/1µs-8         	  256581	      4750 ns/op
BenchmarkNativeSleep/10µs-8        	   68962	     17406 ns/op
BenchmarkNativeSleep/100µs-8       	   10000	    120359 ns/op
BenchmarkNativeSleep/1ms-8         	     972	   1263703 ns/op
BenchmarkNativeSleep/10ms-8        	     100	  10777938 ns/op
BenchmarkNativeSleep/100ms-8       	      10	 101013503 ns/op
BenchmarkNativeSleep/1s-8          	       1	1001136413 ns/op
BenchmarkSleep/1ns-8               	304529434	         3.826 ns/op
BenchmarkSleep/10ns-8              	312554546	         3.814 ns/op
BenchmarkSleep/100ns-8             	313016788	         3.922 ns/op
BenchmarkSleep/1µs-8               	 1326577	       915.8 ns/op
BenchmarkSleep/10µs-8              	  119400	     10098 ns/op
BenchmarkSleep/100µs-8             	   10000	    100199 ns/op
BenchmarkSleep/1ms-8               	    1198	   1000308 ns/op
BenchmarkSleep/10ms-8              	     100	  10000445 ns/op
BenchmarkSleep/100ms-8             	      10	 100008614 ns/op
BenchmarkSleep/1s-8                	       1	1000001382 ns/op
BenchmarkSleepTight/1ns-8          	305970579	         3.951 ns/op
BenchmarkSleepTight/10ns-8         	311431710	         3.840 ns/op
BenchmarkSleepTight/100ns-8        	311112458	         3.911 ns/op
BenchmarkSleepTight/1µs-8          	 1328527	       905.6 ns/op
BenchmarkSleepTight/10µs-8         	  120620	     10033 ns/op
BenchmarkSleepTight/100µs-8        	   10000	    100705 ns/op
BenchmarkSleepTight/1ms-8          	    1200	   1000417 ns/op
BenchmarkSleepTight/10ms-8         	     100	  10000474 ns/op
BenchmarkSleepTight/100ms-8        	      10	 100003390 ns/op
BenchmarkSleepTight/1s-8           	       1	1000001256 ns/op

Single core:

dan@DansMac powernap % go test -run none -bench Sleep -cpu 1
goos: darwin
goarch: amd64
pkg: github.com/morphar/powernap
cpu: Intel(R) Core(TM) i7-1068NG7 CPU @ 2.30GHz
BenchmarkNativeSleep/1ns         	 5196897	       246.4 ns/op
BenchmarkNativeSleep/10ns        	 5188018	       234.8 ns/op
BenchmarkNativeSleep/100ns       	 4249675	       271.0 ns/op
BenchmarkNativeSleep/1µs         	  179382	      9319 ns/op
BenchmarkNativeSleep/10µs        	   73255	     17105 ns/op
BenchmarkNativeSleep/100µs       	   10000	    121338 ns/op
BenchmarkNativeSleep/1ms         	    1053	   1189934 ns/op
BenchmarkNativeSleep/10ms        	     100	  10744706 ns/op
BenchmarkNativeSleep/100ms       	      10	 100730162 ns/op
BenchmarkNativeSleep/1s          	       1	1001129364 ns/op
BenchmarkSleep/1ns               	306946417	         3.837 ns/op
BenchmarkSleep/10ns              	306756348	         3.830 ns/op
BenchmarkSleep/100ns             	309193824	         3.897 ns/op
BenchmarkSleep/1µs               	 1242044	       950.1 ns/op
BenchmarkSleep/10µs              	  119083	     10107 ns/op
BenchmarkSleep/100µs             	   10000	    100318 ns/op
BenchmarkSleep/1ms               	    1198	   1000572 ns/op
BenchmarkSleep/10ms              	     100	  10001685 ns/op
BenchmarkSleep/100ms             	      10	 100004715 ns/op
BenchmarkSleep/1s                	       1	1000001456 ns/op
BenchmarkSleepTight/1ns          	299916702	         3.885 ns/op
BenchmarkSleepTight/10ns         	308808326	         3.813 ns/op
BenchmarkSleepTight/100ns        	307965261	         3.917 ns/op
BenchmarkSleepTight/1µs          	 1268040	       950.3 ns/op
BenchmarkSleepTight/10µs         	  119745	     10036 ns/op
BenchmarkSleepTight/100µs        	   10000	    100139 ns/op
BenchmarkSleepTight/1ms          	    1197	   1000479 ns/op
BenchmarkSleepTight/10ms         	     100	  10000683 ns/op
BenchmarkSleepTight/100ms        	      10	 100000765 ns/op
BenchmarkSleepTight/1s           	       1	1000001293 ns/op

Acknowledgement

The basic idea came from the Rust crate (library) spin_sleep.

About

A more precise sleep for Go

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages