golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
122.27k stars 17.47k forks source link

runtime: gc can add clock tick latency when HPETs are not used #7763

Open 4ad opened 10 years ago

4ad commented 10 years ago
Garbage collector can add latency on the order of clock tick (usually
10ms, 2.5ms, or 1ms) to each run.

This is due to some runtime·usleep(1) and runtime·usleep(100) calls,
which get rounded up to clock period when HPETs are not used.

More details in this thread:
https://groups.google.com/d/topic/golang-codereviews/AxqxYnioBOQ/discussion

Linux uses HPETs by default, but most ARM machines don't have HPETs.
Solaris doesn't use HPETs by default, so this issue affects arm
machines and solaris.

I'm not sure if we need to do anything (maybe we can just assume
"fast" machines), I'm logging it so we can refer to it later.
davecheney commented 10 years ago

Comment 1:

Thanks Aram. Are you saying the underlying issue is runtime.usleep(100us) sleeps for
much longer than expected ?

Labels changed: added release-go1.3, repo-main.

Status changed to Accepted.

4ad commented 10 years ago

Comment 2:

Yes, at the moment it gets rounded up to 10ms on Solaris. I haven't measured on
linux/arm, I expect it to be 2.5ms.
For Solaris, I'll change the runtime to use HPETs (although that has other issues), for
linux/arm we can't do this because there are no HPETs.
4ad commented 10 years ago

Comment 3:

I'd expect Windows XP SP2 (not SP3) also to not support high resolution sleeps at all.
4ad commented 10 years ago

Comment 4:

And of course by 2.5ms I wanted to say 4ms (250Hz).
davecheney commented 10 years ago

Comment 5:

Here are some sample numbers for the observed delay of usleep(1) 
% uname -a
Linux lucky 3.11.0-19-generic #33-Ubuntu SMP Tue Mar 11 18:48:34 UTC 2014 x86_64 x86_64
x86_64 GNU/Linux
% cc time.c && ./a.out
usleep(1) took 72298 ns
panda(~) % uname -a 
Linux panda 3.7.10-x13 #1 SMP Wed Jun 26 07:33:15 UTC 2013 armv7l GNU/Linux
panda(~) % cc time.c && ./a.out
usleep(1) took 122070 ns
In both cases these represent the best results I have seen, during some runs I have seen
the arm numbers spike to 150us and the amd64 numbers spike to 140us

Attachments:

  1. time.c (379 bytes)
4ad commented 10 years ago

Comment 6:

What's CONFIG_HZ, CONFIG_NO_HZ and HIGH_RES_TIMERS on this kernel? What in these files?
/sys/devices/system/clocksource/*/current_clocks
dvyukov commented 10 years ago

Comment 7:

runtime·usleep(1) and runtime·usleep(100) are really intended to be more like
scheduler yields, rather than sleeps
if the system can't handle them, it can just do scheduler yield
4ad commented 10 years ago

Comment 8:

> runtime·usleep(1) and runtime·usleep(100) are really intended to be more
> like scheduler yields, rather than sleeps if the system can't handle them,
> it can just do scheduler yield
Indeed, replacing sleeps with yields solves the problem:
http://paste.ubuntu.com/7234785/
gopherbot commented 10 years ago

Comment 9:

CL https://golang.org/cl/87290043 mentions this issue.
rsc commented 10 years ago

Comment 10:

Labels changed: added release-go1.4, removed release-go1.3.

rsc commented 9 years ago

Comment 11:

Labels changed: added release-none, removed release-go1.4.