2010-06-21 20:53:49 -07:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
|
|
|
|
|
package runtime
|
|
|
|
|
|
2015-11-02 14:09:24 -05:00
|
|
|
import (
|
|
|
|
|
"runtime/internal/atomic"
|
|
|
|
|
"unsafe"
|
|
|
|
|
)
|
2014-08-28 10:46:59 -04:00
|
|
|
|
2010-06-21 20:53:49 -07:00
|
|
|
// GOMAXPROCS sets the maximum number of CPUs that can be executing
|
2020-09-10 10:08:21 +00:00
|
|
|
// simultaneously and returns the previous setting. It defaults to
|
|
|
|
|
// the value of runtime.NumCPU. If n < 1, it does not change the current setting.
|
2010-06-21 20:53:49 -07:00
|
|
|
// This call will go away when the scheduler improves.
|
2014-08-28 10:46:59 -04:00
|
|
|
func GOMAXPROCS(n int) int {
|
2018-03-31 23:14:17 +02:00
|
|
|
if GOARCH == "wasm" && n > 1 {
|
|
|
|
|
n = 1 // WebAssembly has no threads yet, so only one CPU is possible.
|
|
|
|
|
}
|
|
|
|
|
|
2014-09-16 17:26:16 -07:00
|
|
|
lock(&sched.lock)
|
|
|
|
|
ret := int(gomaxprocs)
|
|
|
|
|
unlock(&sched.lock)
|
|
|
|
|
if n <= 0 || n == ret {
|
|
|
|
|
return ret
|
|
|
|
|
}
|
2014-08-28 10:46:59 -04:00
|
|
|
|
runtime: don't hold worldsema across mark phase
This change makes it so that worldsema isn't held across the mark phase.
This means that various operations like ReadMemStats may now stop the
world during the mark phase, reducing latency on such operations.
Only three such operations are still no longer allowed to occur during
marking: GOMAXPROCS, StartTrace, and StopTrace.
For the former it's because any change to GOMAXPROCS impacts GC mark
background worker scheduling and the details there are tricky.
For the latter two it's because tracing needs to observe consistent GC
start and GC end events, and if StartTrace or StopTrace may stop the
world during marking, then it's possible for it to see a GC end event
without a start or GC start event without an end, respectively.
To ensure that GOMAXPROCS and StartTrace/StopTrace cannot proceed until
marking is complete, the runtime now holds a new semaphore, gcsema,
across the mark phase just like it used to with worldsema.
This change is being landed once more after being reverted in the Go
1.14 release cycle, since CL 215157 allows it to have a positive
effect on system performance.
For the benchmark BenchmarkReadMemStatsLatency in the runtime, which
measures ReadMemStats latencies while the GC is exercised, the tail of
these latencies reduced dramatically on an 8-core machine:
name old 50%tile-ns new 50%tile-ns delta
ReadMemStatsLatency-8 4.40M ±74% 0.12M ± 2% -97.35% (p=0.008 n=5+5)
name old 90%tile-ns new 90%tile-ns delta
ReadMemStatsLatency-8 102M ± 6% 0M ±14% -99.79% (p=0.008 n=5+5)
name old 99%tile-ns new 99%tile-ns delta
ReadMemStatsLatency-8 147M ±18% 4M ±57% -97.43% (p=0.008 n=5+5)
Fixes #19812.
Change-Id: If66c3c97d171524ae29f0e7af4bd33509d9fd0bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/216557
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-06-17 19:03:09 +00:00
|
|
|
stopTheWorldGC("GOMAXPROCS")
|
2014-09-16 17:26:16 -07:00
|
|
|
|
2015-05-15 16:00:50 -04:00
|
|
|
// newprocs will be processed by startTheWorld
|
2014-09-16 17:26:16 -07:00
|
|
|
newprocs = int32(n)
|
|
|
|
|
|
runtime: don't hold worldsema across mark phase
This change makes it so that worldsema isn't held across the mark phase.
This means that various operations like ReadMemStats may now stop the
world during the mark phase, reducing latency on such operations.
Only three such operations are still no longer allowed to occur during
marking: GOMAXPROCS, StartTrace, and StopTrace.
For the former it's because any change to GOMAXPROCS impacts GC mark
background worker scheduling and the details there are tricky.
For the latter two it's because tracing needs to observe consistent GC
start and GC end events, and if StartTrace or StopTrace may stop the
world during marking, then it's possible for it to see a GC end event
without a start or GC start event without an end, respectively.
To ensure that GOMAXPROCS and StartTrace/StopTrace cannot proceed until
marking is complete, the runtime now holds a new semaphore, gcsema,
across the mark phase just like it used to with worldsema.
This change is being landed once more after being reverted in the Go
1.14 release cycle, since CL 215157 allows it to have a positive
effect on system performance.
For the benchmark BenchmarkReadMemStatsLatency in the runtime, which
measures ReadMemStats latencies while the GC is exercised, the tail of
these latencies reduced dramatically on an 8-core machine:
name old 50%tile-ns new 50%tile-ns delta
ReadMemStatsLatency-8 4.40M ±74% 0.12M ± 2% -97.35% (p=0.008 n=5+5)
name old 90%tile-ns new 90%tile-ns delta
ReadMemStatsLatency-8 102M ± 6% 0M ±14% -99.79% (p=0.008 n=5+5)
name old 99%tile-ns new 99%tile-ns delta
ReadMemStatsLatency-8 147M ±18% 4M ±57% -97.43% (p=0.008 n=5+5)
Fixes #19812.
Change-Id: If66c3c97d171524ae29f0e7af4bd33509d9fd0bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/216557
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
2019-06-17 19:03:09 +00:00
|
|
|
startTheWorldGC()
|
2014-09-16 17:26:16 -07:00
|
|
|
return ret
|
|
|
|
|
}
|
2010-06-21 20:53:49 -07:00
|
|
|
|
2015-07-10 06:20:51 -07:00
|
|
|
// NumCPU returns the number of logical CPUs usable by the current process.
|
2015-12-04 23:16:50 -05:00
|
|
|
//
|
|
|
|
|
// The set of available CPUs is checked by querying the operating system
|
|
|
|
|
// at process startup. Changes to operating system CPU allocation after
|
|
|
|
|
// process startup are not reflected.
|
2014-08-28 10:46:59 -04:00
|
|
|
func NumCPU() int {
|
|
|
|
|
return int(ncpu)
|
|
|
|
|
}
|
2012-01-25 14:13:11 +11:00
|
|
|
|
2012-02-17 08:49:41 +11:00
|
|
|
// NumCgoCall returns the number of cgo calls made by the current process.
|
2014-08-28 10:46:59 -04:00
|
|
|
func NumCgoCall() int64 {
|
2021-06-22 00:24:05 +00:00
|
|
|
var n = int64(atomic.Load64(&ncgocall))
|
2015-11-02 14:09:24 -05:00
|
|
|
for mp := (*m)(atomic.Loadp(unsafe.Pointer(&allm))); mp != nil; mp = mp.alllink {
|
2014-08-28 10:46:59 -04:00
|
|
|
n += int64(mp.ncgocall)
|
|
|
|
|
}
|
|
|
|
|
return n
|
|
|
|
|
}
|
2010-06-21 20:53:49 -07:00
|
|
|
|
2012-02-17 08:49:41 +11:00
|
|
|
// NumGoroutine returns the number of goroutines that currently exist.
|
2014-08-28 10:46:59 -04:00
|
|
|
func NumGoroutine() int {
|
|
|
|
|
return int(gcount())
|
|
|
|
|
}
|
2019-04-22 23:01:26 -04:00
|
|
|
|
|
|
|
|
//go:linkname debug_modinfo runtime/debug.modinfo
|
|
|
|
|
func debug_modinfo() string {
|
|
|
|
|
return modinfo
|
|
|
|
|
}
|
2021-09-15 17:14:21 -04:00
|
|
|
|
|
|
|
|
// mayMoreStackPreempt is a maymorestack hook that forces a preemption
|
|
|
|
|
// at every possible cooperative preemption point.
|
|
|
|
|
//
|
|
|
|
|
// This is valuable to apply to the runtime, which can be sensitive to
|
|
|
|
|
// preemption points. To apply this to all preemption points in the
|
|
|
|
|
// runtime and runtime-like code, use the following in bash or zsh:
|
|
|
|
|
//
|
|
|
|
|
// X=(-{gc,asm}flags={runtime/...,reflect,sync}=-d=maymorestack=runtime.mayMoreStackPreempt) GOFLAGS=${X[@]}
|
|
|
|
|
//
|
|
|
|
|
// This must be deeply nosplit because it is called from a function
|
|
|
|
|
// prologue before the stack is set up and because the compiler will
|
|
|
|
|
// call it from any splittable prologue (leading to infinite
|
|
|
|
|
// recursion).
|
|
|
|
|
//
|
|
|
|
|
// Ideally it should also use very little stack because the linker
|
|
|
|
|
// doesn't currently account for this in nosplit stack depth checking.
|
|
|
|
|
//
|
|
|
|
|
//go:nosplit
|
|
|
|
|
//
|
|
|
|
|
// Ensure mayMoreStackPreempt can be called for all ABIs.
|
|
|
|
|
//
|
|
|
|
|
//go:linkname mayMoreStackPreempt
|
|
|
|
|
func mayMoreStackPreempt() {
|
|
|
|
|
// Don't do anything on the g0 or gsignal stack.
|
|
|
|
|
g := getg()
|
|
|
|
|
if g == g.m.g0 || g == g.m.gsignal {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// Force a preemption, unless the stack is already poisoned.
|
|
|
|
|
if g.stackguard0 < stackPoisonMin {
|
|
|
|
|
g.stackguard0 = stackPreempt
|
|
|
|
|
}
|
|
|
|
|
}
|