By Sue Spence for the GopherCon 2019 Liveblog on July 25, 2019
Presenter: Patrick Hawley
Liveblogger: Sue Spence
Sometimes we need to tell the go runtime what to do. This talk explains how to control the runtime, why we should, and describes three new ways to control it better.
It's a library used by Go programs while they are executing. It controls things like:
It is a helpful assistant. It is a Go package (https://golang.org/pkg/runtime/). It is not an interpreter (e.g. Python, Ruby) or full runtime environment such as the Java virtual machine. It is useful for profiling and observing what happens during program execution.
Some functions that can be used to control the garbage collector:
Some functions that can be used to control the scheduler:
Patrick asked if anyone had used any of these functions, and then showed a couple of graphics which represented a search of github for such usage. So we have quite likely indirectly used them.
Some more controls, in package runtime/debug:
env vars: GOMAXPROCS (max executing operating system threads), GOGC (turn off garbage collector)
You can get indirect control of the runtime via context
ctx, cancel := context.WithCancel(ctx)
The above requests that all goroutines with ctx, stop. This is scheduler control
Performance reasons. Testing and benchmarks.
go test -cpu 1,2,4
Jaeger tracing uses runtime control to match container CPU quota changes.
We use Goexit() all the time via
t.Fatal("some test failed")
Gosched() yields processor to allow other goroutines to run. This can be put in a tight loop to make sure the CPU isn't hogged.
Thread local state is used by some libs eg Cocoa, OpenGL, libSDL.
GC() is useful for testing, improving performance. For example checking the performance of allocating a slice of integers vs a slice of pointers to int. There are garbage collection implications to handling of values vs pointers so runtime directives can be used to benchmark them.
KeepAlive() holds off garbage collection and there are certain situations where it can be used to stop premature cleanup of e.g. file descriptors.
SetFinalizer() as mentioned sets a function to be called when an obj is no longer needed and can be garbage collected. An example was shown which closes an os.File when it goes out of scope.
Not just performance! Testing, Correctness, Profiling (see relevant slide)
So now that we are convinced that using the Go runtime is good!
These are a thought experiment, they do NOT exist (yet)!
GoAffinity() - requires or suggests that all goroutines of a certain "color" execute on the same CPU.
avoid CPU L1/L2 cache misses
isolation, keeping code of a certain type separate from other types (e.g. math operations vs http)
GoCancel() - cancel all goroutines of a particular "color"
GoSend() - Communicate with goroutines of a particular "color"
a) We should never control the Go runtime directly
b) Controlling the runtime is bad programming
c) ids for Go routines?? Never! Color is just an alias for ids.. d) Let's just make the runtime better
a) Performance and testing are really necessary items that runtime helps with
b) User space ought to be fair game for us to control. It's not the kernel, which is legitimately off-limits
Let users have tools, empower them
c) Use types, not tokens. Also, why not be open to ids?
d) YES, make the runtime better. But also give programmers more options.