You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The lost time is in the call to sleep in the read loop.
TL;DR; Ask OpenBSD (at least an amd64 6.2 OpenBSD) to sleep for 1 millisecond, and it will sleep for 20 times that. So tests that use a 1ms sleep in each iteration will take a lot longer on OpenBSD.
I tried this on Debian Linux, FreeBSD and OpenBSD. All amd64 virtual machines.
Each reads and writes in 65536 byte chunks. Each iterates the write loop 1600 times. Linux needs 1600 iterations for the read loop, and the two BSDs need 1601 iterations.
The request for a 1 ms sleep in each iteration of the read loop is actually taking 18 to 22 ms on OpenBSD. The same call takes just over a ms on a similarly setup FreeBSD machine and even closer to a single ms on a similarly setup Debian machine.
Since the resolution seems to be around 20ms for OpenBSD, and it is the worst offender of the three I tested, I added logic around the call to sleep so it would only be called once every 20 times through the loop, and changed the request to sleep from 1ms to 20ms. This improved the results for OpenBSD without making things worse for FreeBSD or Linux. The TestTransportFlowControl test can be made to succeed in about 2 seconds. Here are the three values I got.
The accuracy of the Linux sleep is much higher than the BSDs' sleep. The Linux sleep for 20ms averaged taking 20.3ms, FreeBSD averaged 24ms and OpenBSD averaged 30ms.
That's not a typo. The call time.Sleep(20 * time.Millisecond),
with two calls to time.Now before and after, takes on average 30 milliseconds on OpenBSD. They just don't want to give you an accurate timer for security reasons I think. If you ask to sleep for one millisecond, they make you sleep about 20 milliseconds on average. But ask for 20, and you get between 24 and 40, with the average being 30.
Any golang tests that try to use a 1 millisecond timer on OpenBSD are not going to compare well with results from the other OSes.
To convince myself this wasn't some other fault of golang, I wrote a trivial c program to call nanosleep 1000 times for 1ms each. Sure enough, on Linux and FreeBSD, the program took just over a second to run. On OpenBSD, it took just over 20 seconds to run. Even a C program can't expect to sleep for 1ms at a time on OpenBSD.