Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: runtime: flag to disable runtime override of GODEBUG #60943

Open
dpcollins-google opened this issue Jun 22, 2023 · 7 comments
Open
Labels
Milestone

Comments

@dpcollins-google
Copy link

dpcollins-google commented Jun 22, 2023

I would like to make a change to the go runtime to convert the debug variables parsed from GODEBUG to constants, and disable GODEBUG overriding at runtime.

Many of these constants are used to gate low level checks in the depths of the garbage collector or runtime, and if they were true constants, some of these checks could be elided by constant propagation. An example is the findobject function which would be able to skip some checks if debug.invalidptr were known to be a fixed constant 0. (internal reference b/288410395, these have substantial cost)

I would like to propose a new flag to cgo, strawman fixed_godebug, that when provided generates constant values for these fields as-if the GODEBUG env var had the value of fixed_godebug at runtime.

The work needed to implement this would be:

  1. Split out debug itself and functions that modify debug.* fields into a new file, runtime/godebug.go
  2. Move all debug fields to top level variables named debug* and all their usages in the runtime/ package. These are not exported so should not be breaking.
  3. When the fixed_godebug flag is not empty, have cgo generate a replacement for godebug.go that replaces the var block with debug* values with a const block that sets all values inline, and makes all modifying functions log and do nothing.
@gopherbot gopherbot added this to the Proposal milestone Jun 22, 2023
@seankhliao seankhliao changed the title proposal: Offer a flag to fix GODEBUG at compile time affected/package: runtime proposal: runtime: flag to disable runtime override of GODEBUG Jun 22, 2023
@ericlagergren
Copy link
Contributor

Why add it to the cgo tool?

@dpcollins-google
Copy link
Author

Why add it to the cgo tool?

I'm not super picky about where its added, is there a better place you would suggest to perform this manipulation?

@ianlancetaylor
Copy link
Contributor

I don't understand what cgo has to do with this at all.

More importantly, you said what you want, but you didn't say why you want it. What is the goal here? What is the problem being solved? Thanks.

@dpcollins-google
Copy link
Author

I don't understand what cgo has to do with this at all.

some piece of tooling needs to swap out the godebug.go file inside of the go runtime that has:

var (
debugcgocheck           int32
debugclobberfree        int32
debugdontfreezetheworld int32
...
)

to:

const (
debugcgocheck           int32  = 0
debugclobberfree        int32 = 0
debugdontfreezetheworld int32 = 1
...
)

Is there a better piece of the compiler ecosystem to do this?

What is the goal here? What is the problem being solved? Thanks.

Based on horizontal profiling, a lot of cycles are spent within the go garbage collector (and presumably in other places in the core runtime) on performing boolean checks that would be removed via constant propagation if the debug variables were constants. I would like to allow users (like myself) who don't want these debug checks to reduce the overhead of the go runtime further by disabling these constants at compile time instead of runtime.

@ianlancetaylor
Copy link
Contributor

Is there a better piece of the compiler ecosystem to do this?

Maybe there is some terminology issue here. In the Go ecosystem cgo refers to https://pkg.go.dev/cmd/cgo. That tool is not going to be swapping out any files in the Go runtime. That's not what it's for. But this is a detail.

Based on horizontal profiling, a lot of cycles are spent within the go garbage collector (and presumably in other places in the core runtime) on performing boolean checks that would be removed via constant propagation if the debug variables were constants.

If that is the only goal here, then our first step should be to try to analyze this problem and see if we can fix it in the compiler or runtime in some way, without having to change the semantics of GODEBUG. Would you like to open a different issue with some profiles showing the problem? Thanks.

@dpcollins-google
Copy link
Author

Maybe there is some terminology issue here

Yes, this is my fault. I think the tool I should have referenced was gc, but my intent was for this to be built into the compiler infrastructure itself, whichever piece makes the most sense.

then our first step should be to try to analyze this problem and see if we can fix it in the compiler or runtime in some way

The problem trying to be fixed is: there exist runtime branches and checks in compiled go code (in the garbage collector in particular) that incur a lot of cost, but only exist because GODEBUG can be changed at runtime. If GODEBUG is fixed at compile time, these branches and checks go away.

@mknyszek
Copy link
Contributor

mknyszek commented Jun 23, 2023

Generally these debug variables are carefully avoided on hot paths, or are placed behind a branch that's already rare. For invalidptr checked in findObject specifically, that falls under a path that's taken basically only for broken programs IIRC. In real-world use that branch should never be taken. There may be something to save there in terms of instruction cache pressure? That's an interesting one too since I think it only actually does anything if the compiler builds with -clobberdead as well. That seems like it might just be cleanup (absent any performance difference even) to make it compile-time? CC @cherrymui

If I'm wrong, that's great, and that's nice low-hanging fruit, but I'd like to see some more evidence that these debug variables are actually impacting performance. It would be pretty straightforward to patch out certain branches and run some of our benchmarks just to get an idea of the difference.

Also, I think the right thing to do for at least some of these, if they were to become compile-time constants, would be to turn them into GOEXPERIMENTs, kind of like how we did for GOEXPERIMENT=cgocheck2, which used to be GODEBUG=cgocheck=2 but had to change for other reasons.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Incoming
Development

No branches or pull requests

5 participants