From aa5f6e8f49bb9aa74d4de02cd5e5e086960bd1fe Mon Sep 17 00:00:00 2001 From: Michael Vogt Date: Wed, 29 May 2019 18:55:26 +0200 Subject: snapd: ensure GOMAXPROCS is at least 2 The Go scheduler by default has a single operating system thread per processor core, and does it's own goroutine scheduling inside of that thread. For I/O operations that the Go runtime knows about, it has mechanisms to reschedule goroutines so the system thread isn't blocked waiting for I/O. If a goroutine performs a blocking system call which the go runtime doesn't have special optimizations for, the system thread can become blocked waiting for the syscall. This can dramatically reduce runtime performance, and the problem is much worse on single processor systems because there is normally only a single system thread. We workaround by increasing the armound of procs to a minimum of two. --- cmd/snapd/main.go | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/cmd/snapd/main.go b/cmd/snapd/main.go index aafabbfe98..f68cb0a86c 100644 --- a/cmd/snapd/main.go +++ b/cmd/snapd/main.go @@ -23,6 +23,7 @@ import ( "fmt" "os" "os/signal" + "runtime" "syscall" "time" @@ -53,6 +54,24 @@ func init() { func main() { cmd.ExecInSnapdOrCoreSnap() + // The Go scheduler by default has a single operating system + // thread per processor core, and does it's own goroutine + // scheduling inside of that thread. For I/O operations that + // the Go runtime knows about, it has mechanisms to reschedule + // goroutines so the system thread isn't blocked waiting for + // I/O. If a goroutine performs a blocking system call which + // the go runtime doesn't have special optimizations for, the + // system thread can become blocked waiting for the syscall. + // This can dramatically reduce runtime performance, and the + // problem is much worse on single processor systems because + // there is normally only a single system thread. + // + // We workaround by increasing the armound of procs to a + // minimum of two. + if runtime.GOMAXPROCS(-1) == 1 { + runtime.GOMAXPROCS(2) + } + ch := make(chan os.Signal, 2) signal.Notify(ch, syscall.SIGINT, syscall.SIGTERM) if err := run(ch); err != nil { -- cgit v1.2.3 From 891242282a6b255dc8057697717f9d96c2f10a4a Mon Sep 17 00:00:00 2001 From: Maciej Borzecki Date: Fri, 31 May 2019 11:13:54 +0200 Subject: cmd/snap: tweak GOMAXPROCS comment Signed-off-by: Maciej Borzecki --- cmd/snapd/main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/snapd/main.go b/cmd/snapd/main.go index f68cb0a86c..6940cf06a4 100644 --- a/cmd/snapd/main.go +++ b/cmd/snapd/main.go @@ -55,7 +55,7 @@ func main() { cmd.ExecInSnapdOrCoreSnap() // The Go scheduler by default has a single operating system - // thread per processor core, and does it's own goroutine + // thread per processor core, and does its own goroutine // scheduling inside of that thread. For I/O operations that // the Go runtime knows about, it has mechanisms to reschedule // goroutines so the system thread isn't blocked waiting for @@ -66,7 +66,7 @@ func main() { // problem is much worse on single processor systems because // there is normally only a single system thread. // - // We workaround by increasing the armound of procs to a + // We workaround by increasing the number of procs to a // minimum of two. if runtime.GOMAXPROCS(-1) == 1 { runtime.GOMAXPROCS(2) -- cgit v1.2.3