-
Notifications
You must be signed in to change notification settings - Fork 18k
runtime: make GOMAXPROCS
cfs-aware on GOOS=linux
#33803
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
Comments
I really have to disagree with some of the latter suggestions in kubernetes/kubernetes#67577 Some background on uber-go/automaxprocs#13 (changing from
I'll reprise (copied with some edits) my description from that issue here for easy reading:
|
Noting: #19378 (comment) explores some GC-CFS relationship |
For comparative purposes, Oracle blog post about Java adding similar support ( especially for GC threads ) |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
(I'm not sure this has to be a proposal at all. This is more like a bug report. See https://golang.org/s/proposal.) |
Changing this from a proposal into a feature request for the runtime package. |
GOMAXPROCS
cfs-aware on GOOS=linux
GOMAXPROCS
cfs-aware on GOOS=linux
This comment was marked as outdated.
This comment was marked as outdated.
Perhaps due to etcd failing due to mismatch between the CPU limits and the apparent available CPUs according to GOMAXPROCS See golang/go#33803
Perhaps due to etcd failing due to mismatch between the CPU limits and the apparent available CPUs according to GOMAXPROCS See golang/go#33803
Perhaps due to etcd failing due to mismatch between the CPU limits and the apparent available CPUs according to GOMAXPROCS See golang/go#33803
GOMAXPROCS subsumes NumCPU for the purpose of sizing semaphores. If users set CPU affinity, then GOMAXPROCS will reflect that. If users only set GOMAXPROCS, then NumCPU would be inaccurate. Additionally, there are plans to make GOMAXPROCS aware of CPU quotas (golang/go#33803). Users are still advised to set CPU affinity instead of relying on GOMAXPROCS to limit CPU usage, because Staticcheck shells out to the underlying build system, which together with Staticcheck would be able to use more CPU than intended if limited by just GOMAXPROCS.
see golang/go#33803 for more info
see golang/go#33803 for more info
see golang/go#33803 for more info
I have filed a concrete proposal for how we can do this at #73193. Please take a look. |
Problem
The default setting of
runtime.GOMAXPROCS()
(to be the number of os-apparent processors) can be greatly misaligned with container cpu quota (e.g. as implemented through cfs bandwidth control by docker).This can lead to large latency artifacts in programs, especially under peak load, or when saturating all processors during background GC phases.
The smaller the container / larger the machine = the worse this effect becomes: let's say you deploy a fleet of micro service workers, each container having a cpu quota of 4, on a fleet of 32 processor[1] machines.
To understand why, you really have to understand the CFS quota mechanism; this blog post does well (with pictures); this kubernetes issue further explores the topic (especially as it relates to a recently resolved kernel cpu accounting bug). But to summarize it briefly for this issue:
period
, say 100msquota
, say 400ms to affect a 4-processor quotaperiod
, once the process group exceeds itsquota
it is throttledRunning an application workload at a reasonable level of cpu efficiency makes it quite likely that you'll be spiking up to your full quota and getting throttled.
Background waste workload, like concurrent GC[2], is especially likely to cause quota exhaustion.
I hesitate to even call this a "tail latency" problem; the artifacts are visible in the main body of and can shift the entire latency distribution.
Solution
If you care about latency, reliability, predictability (... insert more *ilities to taste), then the correct thing to do is to never exceed your cpu quota, by setting
GOMAXPROCS=max(1, floor(cpu_quota))
.Using this as a default for GOMAXPROCS makes the world safe again, which is why we use uber-go/automaxprocs in all of our microservices.
NOTEs
The text was updated successfully, but these errors were encountered: