golang / go

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

runtime: read-only accessor for gcpercent #39419

Open bsiegert opened 4 years ago

bsiegert commented 4 years ago

I would like to programmatically access the current value of GOGC in my program (for logging it, with various runtime stats).

For GOMAXPROCS, I can call runtime.GOMAXPROCS(0) to get the current value without changing it. However, for GOGC, I see no way of reading the value without writing. I could do a two-step call like

percent := debug.SetGCPercent(100)
debug.SetGCPercent(percent)

but I am worried about the disruption that this may cause in a program that is under load and that has a non-standard GOGC value in the first place.

The documentation for SetGCPercent says that a negative value will disable GC, however there is no documented effect for calling it with 0. Maybe this could be defined to just return the current value, like in GOMAXPROCS? This would just be a matter of making runtime.setGCPercent return early in this case.

ianlancetaylor commented 4 years ago

CC @aclements @mknyszek

mknyszek commented 4 years ago

Judging by the code, SetGCPercent(0) appears to have the effect of making the trigger ratio 0, so basically a goroutine is going to start a GC whenever it can (except that it has to block until sweeping is done, but it'll help) and the application is basically going to try to continuously stay in the mark phase. I'm not sure if this is useful to anyone, but it is the behavior we currently support (and who knows, maybe someone out there actually uses it; we would break them by changing it). It's sort of documented in that it's in-line with the definition of GOGC: we just simply don't let the heap grow at all before triggering the next GC. I agree this could be made clearer.

As for whether to add a new API call to get the value without modifying it, I'm not opposed. The value can be read by just taking the heap lock. It would've been nice to have it work like GOMAXPROCS for symmetry, but I don't think it's possible at this point without duplicating the API surface. I think to keep things orthogonal if we add something new, whatever we add should just read the value like you suggest and do nothing else.

ianlancetaylor commented 4 years ago

Well, if we can't think of anything else:

    n := debug.SetGCPercent(100)
    debug.SetGCPercent(n)
    // Now n is the GOGC value.
    // If you do this at init time it seems unlikely to break anything much.