Repository: syncthing/syncthing (language: go)

Issue:
syncthing should be cgroup aware
### Does your log mention database corruption?

No.

### Include required information

[Go is not cgroup aware](https://github.com/golang/go/issues/33803). This means that Syncthing will be throttled hard in containerised environments with CPU limits.

The below screenshot shows a Syncthing container with a CPU limit of 1 core in Kubernetes. The first half of the time series is on a 13600k, with 20 threads. The second half is when the machine changed to use an EPYC 7763 with 128 threads.

![image](https://github.com/syncthing/syncthing/assets/9749173/e8d65ce3-3b4d-48b8-b64c-d709b6f85791)

This was sort of mentioned in another issue, but not really - #9357. Syncthing should probably use [automaxprocs](https://github.com/uber-go/automaxprocs).


Discussion / hints:

Fix patch:
diff --git a/build.go b/build.go
index 6f76e4735b6..18957bfc723 100644
--- a/build.go
+++ b/build.go
@@ -34,6 +34,7 @@ import (
 	"time"
 
 	buildpkg "github.com/syncthing/syncthing/lib/build"
+	_ "go.uber.org/automaxprocs"
 )
 
 var (
diff --git a/cmd/stcompdirs/main.go b/cmd/stcompdirs/main.go
index 62565be5e84..3a3f0174ea7 100644
--- a/cmd/stcompdirs/main.go
+++ b/cmd/stcompdirs/main.go
@@ -16,6 +16,7 @@ import (
 	"path/filepath"
 
 	"github.com/syncthing/syncthing/lib/sha256"
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {
diff --git a/cmd/stcrashreceiver/main.go b/cmd/stcrashreceiver/main.go
index 197466a9a49..788b146575f 100644
--- a/cmd/stcrashreceiver/main.go
+++ b/cmd/stcrashreceiver/main.go
@@ -23,11 +23,11 @@ import (
 	"path/filepath"
 
 	"github.com/alecthomas/kong"
+	raven "github.com/getsentry/raven-go"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 	"github.com/syncthing/syncthing/lib/sha256"
 	"github.com/syncthing/syncthing/lib/ur"
-
-	raven "github.com/getsentry/raven-go"
+	_ "go.uber.org/automaxprocs"
 )
 
 const maxRequestSize = 1 << 20 // 1 MiB
diff --git a/cmd/stdisco/main.go b/cmd/stdisco/main.go
index 7b820fcc4b0..d0e52d0311c 100644
--- a/cmd/stdisco/main.go
+++ b/cmd/stdisco/main.go
@@ -18,6 +18,7 @@ import (
 	"github.com/syncthing/syncthing/lib/beacon"
 	"github.com/syncthing/syncthing/lib/discover"
 	"github.com/syncthing/syncthing/lib/protocol"
+	_ "go.uber.org/automaxprocs"
 )
 
 var (
diff --git a/cmd/stdiscosrv/main.go b/cmd/stdiscosrv/main.go
index f7f968c86d6..fa1ce3b721d 100644
--- a/cmd/stdiscosrv/main.go
+++ b/cmd/stdiscosrv/main.go
@@ -24,6 +24,7 @@ import (
 	"github.com/syncthing/syncthing/lib/tlsutil"
 	"github.com/syndtr/goleveldb/leveldb/opt"
 	"github.com/thejerf/suture/v4"
+	_ "go.uber.org/automaxprocs"
 )
 
 const (
diff --git a/cmd/stevents/main.go b/cmd/stevents/main.go
index b723ab54228..92224a7d682 100644
--- a/cmd/stevents/main.go
+++ b/cmd/stevents/main.go
@@ -14,6 +14,8 @@ import (
 	"net/http"
 	"os"
 	"time"
+
+	_ "go.uber.org/automaxprocs"
 )
 
 type event struct {
diff --git a/cmd/stfileinfo/main.go b/cmd/stfileinfo/main.go
index 2efb99611bd..762e51335fa 100644
--- a/cmd/stfileinfo/main.go
+++ b/cmd/stfileinfo/main.go
@@ -15,6 +15,7 @@ import (
 
 	"github.com/syncthing/syncthing/lib/protocol"
 	"github.com/syncthing/syncthing/lib/scanner"
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {
diff --git a/cmd/stfinddevice/main.go b/cmd/stfinddevice/main.go
index f6e94a3ba5c..48f7f862e79 100644
--- a/cmd/stfinddevice/main.go
+++ b/cmd/stfinddevice/main.go
@@ -20,6 +20,7 @@ import (
 	"github.com/syncthing/syncthing/lib/discover"
 	"github.com/syncthing/syncthing/lib/events"
 	"github.com/syncthing/syncthing/lib/protocol"
+	_ "go.uber.org/automaxprocs"
 )
 
 var timeout = 5 * time.Second
diff --git a/cmd/stfindignored/main.go b/cmd/stfindignored/main.go
index 7ec7969f347..cb93e07b1da 100644
--- a/cmd/stfindignored/main.go
+++ b/cmd/stfindignored/main.go
@@ -14,6 +14,7 @@ import (
 
 	"github.com/syncthing/syncthing/lib/fs"
 	"github.com/syncthing/syncthing/lib/ignore"
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {
diff --git a/cmd/stgenfiles/main.go b/cmd/stgenfiles/main.go
index e7b572257de..a03f0ce29f3 100644
--- a/cmd/stgenfiles/main.go
+++ b/cmd/stgenfiles/main.go
@@ -15,6 +15,8 @@ import (
 	"os"
 	"path/filepath"
 	"time"
+
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {
diff --git a/cmd/strelaypoolsrv/main.go b/cmd/strelaypoolsrv/main.go
index 81bc116933f..c3f8cc89d1b 100644
--- a/cmd/strelaypoolsrv/main.go
+++ b/cmd/strelaypoolsrv/main.go
@@ -21,18 +21,18 @@ import (
 	"time"
 
 	lru "github.com/hashicorp/golang-lru/v2"
-	"github.com/syncthing/syncthing/lib/httpcache"
-	"github.com/syncthing/syncthing/lib/protocol"
-
 	"github.com/oschwald/geoip2-golang"
 	"github.com/prometheus/client_golang/prometheus"
 	"github.com/prometheus/client_golang/prometheus/promhttp"
 	"github.com/syncthing/syncthing/cmd/strelaypoolsrv/auto"
 	"github.com/syncthing/syncthing/lib/assets"
+	"github.com/syncthing/syncthing/lib/httpcache"
+	"github.com/syncthing/syncthing/lib/protocol"
 	"github.com/syncthing/syncthing/lib/rand"
 	"github.com/syncthing/syncthing/lib/relay/client"
 	"github.com/syncthing/syncthing/lib/sync"
 	"github.com/syncthing/syncthing/lib/tlsutil"
+	_ "go.uber.org/automaxprocs"
 )
 
 type location struct {
diff --git a/cmd/strelaysrv/main.go b/cmd/strelaysrv/main.go
index bc24912f6bd..99000624ae9 100644
--- a/cmd/strelaysrv/main.go
+++ b/cmd/strelaysrv/main.go
@@ -20,18 +20,17 @@ import (
 	"time"
 
 	"github.com/syncthing/syncthing/lib/build"
+	"github.com/syncthing/syncthing/lib/config"
 	"github.com/syncthing/syncthing/lib/events"
+	"github.com/syncthing/syncthing/lib/nat"
 	"github.com/syncthing/syncthing/lib/osutil"
+	_ "github.com/syncthing/syncthing/lib/pmp"
+	syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
 	"github.com/syncthing/syncthing/lib/relay/protocol"
 	"github.com/syncthing/syncthing/lib/tlsutil"
-	"golang.org/x/time/rate"
-
-	"github.com/syncthing/syncthing/lib/config"
-	"github.com/syncthing/syncthing/lib/nat"
-	_ "github.com/syncthing/syncthing/lib/pmp"
 	_ "github.com/syncthing/syncthing/lib/upnp"
-
-	syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
+	_ "go.uber.org/automaxprocs"
+	"golang.org/x/time/rate"
 )
 
 var (
diff --git a/cmd/stsigtool/main.go b/cmd/stsigtool/main.go
index ab4c46b3e83..021de6365e4 100644
--- a/cmd/stsigtool/main.go
+++ b/cmd/stsigtool/main.go
@@ -14,6 +14,7 @@ import (
 
 	"github.com/syncthing/syncthing/lib/signature"
 	"github.com/syncthing/syncthing/lib/upgrade"
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {
diff --git a/cmd/stupgrades/main.go b/cmd/stupgrades/main.go
index 3e4da7966b1..26c12598851 100644
--- a/cmd/stupgrades/main.go
+++ b/cmd/stupgrades/main.go
@@ -21,6 +21,7 @@ import (
 	"github.com/alecthomas/kong"
 	"github.com/syncthing/syncthing/lib/httpcache"
 	"github.com/syncthing/syncthing/lib/upgrade"
+	_ "go.uber.org/automaxprocs"
 )
 
 type cli struct {
diff --git a/cmd/stvanity/main.go b/cmd/stvanity/main.go
index 8917163b474..5ca9b2624ac 100644
--- a/cmd/stvanity/main.go
+++ b/cmd/stvanity/main.go
@@ -27,6 +27,7 @@ import (
 	"time"
 
 	"github.com/syncthing/syncthing/lib/protocol"
+	_ "go.uber.org/automaxprocs"
 )
 
 type result struct {
diff --git a/cmd/stwatchfile/main.go b/cmd/stwatchfile/main.go
index 0a8bd4dc183..73eebfdf40f 100644
--- a/cmd/stwatchfile/main.go
+++ b/cmd/stwatchfile/main.go
@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"github.com/syncthing/syncthing/lib/sha256"
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {
diff --git a/cmd/syncthing/main.go b/cmd/syncthing/main.go
index 6d221629003..65c1600813d 100644
--- a/cmd/syncthing/main.go
+++ b/cmd/syncthing/main.go
@@ -33,6 +33,7 @@ import (
 	"github.com/alecthomas/kong"
 	"github.com/thejerf/suture/v4"
 	"github.com/willabides/kongplete"
+	_ "go.uber.org/automaxprocs"
 
 	"github.com/syncthing/syncthing/cmd/syncthing/cli"
 	"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
diff --git a/cmd/ursrv/main.go b/cmd/ursrv/main.go
index 25bdb0446ed..7019dd96609 100644
--- a/cmd/ursrv/main.go
+++ b/cmd/ursrv/main.go
@@ -13,6 +13,7 @@ import (
 	"github.com/alecthomas/kong"
 	"github.com/syncthing/syncthing/cmd/ursrv/aggregate"
 	"github.com/syncthing/syncthing/cmd/ursrv/serve"
+	_ "go.uber.org/automaxprocs"
 )
 
 type CLI struct {
diff --git a/go.mod b/go.mod
index 6a3954339f9..2a728544425 100644
--- a/go.mod
+++ b/go.mod
@@ -38,6 +38,7 @@ require (
 	github.com/urfave/cli v1.22.14
 	github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
 	github.com/willabides/kongplete v0.4.0
+	go.uber.org/automaxprocs v1.5.3
 	golang.org/x/crypto v0.19.0
 	golang.org/x/net v0.21.0
 	golang.org/x/sys v0.17.0
diff --git a/go.sum b/go.sum
index ef909d96ecf..d5687eddf26 100644
--- a/go.sum
+++ b/go.sum
@@ -170,6 +170,8 @@ github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSg
 github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
 github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
 github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
+github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
+github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
 github.com/prometheus/client_golang v1.18.0 h1:HzFfmkOzH5Q8L8G+kSJKUx5dtG87sewO+FoDDqP5Tbk=
 github.com/prometheus/client_golang v1.18.0/go.mod h1:T+GXkCk5wSJyOqMIzVgvvjFDlkOQntgjkJWKrN5txjA=
 github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
@@ -229,6 +231,8 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
 github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
 github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
 github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
+go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
 go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
 go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=


Test patch:
diff --git a/cmd/strelaysrv/testutil/main.go b/cmd/strelaysrv/testutil/main.go
index 4213c525143..6138d6bdf41 100644
--- a/cmd/strelaysrv/testutil/main.go
+++ b/cmd/strelaysrv/testutil/main.go
@@ -17,6 +17,7 @@ import (
 	syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
 	"github.com/syncthing/syncthing/lib/relay/client"
 	"github.com/syncthing/syncthing/lib/relay/protocol"
+	_ "go.uber.org/automaxprocs"
 )
 
 func main() {