summaryrefslogtreecommitdiff
path: root/vendor/github.com/KimMachineGun
diff options
context:
space:
mode:
authorLibravatar dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>2024-01-22 09:35:23 +0000
committerLibravatar GitHub <noreply@github.com>2024-01-22 09:35:23 +0000
commita858831387f5e423c855ff3c5611fc80209f44b0 (patch)
tree059dcfc37228670e1e2aa20db4a36bb3cef40ef6 /vendor/github.com/KimMachineGun
parent[bugfix] fix array type for also_known_as_uris (#2553) (diff)
downloadgotosocial-a858831387f5e423c855ff3c5611fc80209f44b0.tar.xz
[chore]: Bump github.com/KimMachineGun/automemlimit from 0.4.0 to 0.5.0 (#2560)
Diffstat (limited to 'vendor/github.com/KimMachineGun')
-rw-r--r--vendor/github.com/KimMachineGun/automemlimit/README.md18
-rw-r--r--vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go91
-rw-r--r--vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups_linux.go98
-rw-r--r--vendor/github.com/KimMachineGun/automemlimit/memlimit/exp_system.go14
-rw-r--r--vendor/github.com/KimMachineGun/automemlimit/memlimit/experiment.go59
-rw-r--r--vendor/github.com/KimMachineGun/automemlimit/memlimit/memlimit.go45
6 files changed, 221 insertions, 104 deletions
diff --git a/vendor/github.com/KimMachineGun/automemlimit/README.md b/vendor/github.com/KimMachineGun/automemlimit/README.md
index 192bc0b6f..c0e66d2a7 100644
--- a/vendor/github.com/KimMachineGun/automemlimit/README.md
+++ b/vendor/github.com/KimMachineGun/automemlimit/README.md
@@ -8,6 +8,14 @@ Automatically set `GOMEMLIMIT` to match Linux [cgroups(7)](https://man7.org/linu
See more details about `GOMEMLIMIT` [here](https://tip.golang.org/doc/gc-guide#Memory_limit).
+## Notice
+
+Version `v0.5.0` introduces a fallback to system memory limits as an experimental feature when cgroup limits are unavailable. Activate this by setting `AUTOMEMLIMIT_EXPERIMENT=system`.
+You can also use system memory limits via `memlimit.FromSystem` provider directly.
+
+This feature is under evaluation and might become a default or be removed based on user feedback.
+If you have any feedback about this feature, please open an issue.
+
## Installation
```shell
@@ -34,9 +42,17 @@ import "github.com/KimMachineGun/automemlimit/memlimit"
func init() {
memlimit.SetGoMemLimitWithOpts(
memlimit.WithRatio(0.9),
- memlimit.WithEnv(),
memlimit.WithProvider(memlimit.FromCgroup),
)
+ memlimit.SetGoMemLimitWithOpts(
+ memlimit.WithRatio(0.9),
+ memlimit.WithProvider(
+ memlimit.ApplyFallback(
+ memlimit.FromCgroup,
+ memlimit.FromSystem,
+ ),
+ ),
+ )
memlimit.SetGoMemLimitWithEnv()
memlimit.SetGoMemLimit(0.9)
memlimit.SetGoMemLimitWithProvider(memlimit.Limit(1024*1024), 0.9)
diff --git a/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go b/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go
index cfe6d0f60..979bd3937 100644
--- a/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go
+++ b/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups.go
@@ -1,91 +1,12 @@
-//go:build linux
-// +build linux
-
package memlimit
import (
- "path/filepath"
-
- "github.com/containerd/cgroups/v3"
- "github.com/containerd/cgroups/v3/cgroup1"
- "github.com/containerd/cgroups/v3/cgroup2"
+ "errors"
)
-const (
- cgroupMountPoint = "/sys/fs/cgroup"
+var (
+ // ErrNoCgroup is returned when the process is not in cgroup.
+ ErrNoCgroup = errors.New("process is not in cgroup")
+ // ErrCgroupsNotSupported is returned when the system does not support cgroups.
+ ErrCgroupsNotSupported = errors.New("cgroups is not supported on this system")
)
-
-// FromCgroup returns the memory limit based on the cgroups version on this system.
-func FromCgroup() (uint64, error) {
- switch cgroups.Mode() {
- case cgroups.Legacy:
- return FromCgroupV1()
- case cgroups.Hybrid:
- return FromCgroupHybrid()
- case cgroups.Unified:
- return FromCgroupV2()
- }
- return 0, ErrNoCgroup
-}
-
-// FromCgroupV1 returns the memory limit from the cgroup v1.
-func FromCgroupV1() (uint64, error) {
- cg, err := cgroup1.Load(cgroup1.RootPath, cgroup1.WithHiearchy(
- cgroup1.SingleSubsystem(cgroup1.Default, cgroup1.Memory),
- ))
- if err != nil {
- return 0, err
- }
-
- metrics, err := cg.Stat(cgroup1.IgnoreNotExist)
- if err != nil {
- return 0, err
- }
-
- if limit := metrics.GetMemory().GetHierarchicalMemoryLimit(); limit != 0 {
- return limit, nil
- }
-
- return 0, ErrNoLimit
-}
-
-// FromCgroupHybrid returns the memory limit from the cgroup v1 or v2.
-// It checks the cgroup v2 first, and if it fails, it falls back to cgroup v1.
-func FromCgroupHybrid() (uint64, error) {
- limit, err := fromCgroupV2(filepath.Join(cgroupMountPoint, "unified"))
- if err == nil {
- return limit, nil
- } else if err != ErrNoLimit {
- return 0, err
- }
-
- return FromCgroupV1()
-}
-
-// FromCgroupV2 returns the memory limit from the cgroup v2.
-func FromCgroupV2() (uint64, error) {
- return fromCgroupV2(cgroupMountPoint)
-}
-
-func fromCgroupV2(mountPoint string) (uint64, error) {
- path, err := cgroup2.NestedGroupPath("")
- if err != nil {
- return 0, err
- }
-
- m, err := cgroup2.Load(path, cgroup2.WithMountpoint(mountPoint))
- if err != nil {
- return 0, err
- }
-
- stats, err := m.Stat()
- if err != nil {
- return 0, err
- }
-
- if limit := stats.GetMemory().GetUsageLimit(); limit != 0 {
- return limit, nil
- }
-
- return 0, ErrNoLimit
-}
diff --git a/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups_linux.go b/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups_linux.go
new file mode 100644
index 000000000..98a954873
--- /dev/null
+++ b/vendor/github.com/KimMachineGun/automemlimit/memlimit/cgroups_linux.go
@@ -0,0 +1,98 @@
+//go:build linux
+// +build linux
+
+package memlimit
+
+import (
+ "math"
+ "os"
+ "path/filepath"
+
+ "github.com/containerd/cgroups/v3"
+ "github.com/containerd/cgroups/v3/cgroup1"
+ "github.com/containerd/cgroups/v3/cgroup2"
+)
+
+const (
+ cgroupMountPoint = "/sys/fs/cgroup"
+)
+
+// FromCgroup returns the memory limit based on the cgroups version on this system.
+func FromCgroup() (uint64, error) {
+ switch cgroups.Mode() {
+ case cgroups.Legacy:
+ return FromCgroupV1()
+ case cgroups.Hybrid:
+ return FromCgroupHybrid()
+ case cgroups.Unified:
+ return FromCgroupV2()
+ }
+ return 0, ErrNoCgroup
+}
+
+// FromCgroupV1 returns the memory limit from the cgroup v1.
+func FromCgroupV1() (uint64, error) {
+ cg, err := cgroup1.Load(cgroup1.RootPath, cgroup1.WithHiearchy(
+ cgroup1.SingleSubsystem(cgroup1.Default, cgroup1.Memory),
+ ))
+ if err != nil {
+ return 0, err
+ }
+
+ metrics, err := cg.Stat(cgroup1.IgnoreNotExist)
+ if err != nil {
+ return 0, err
+ }
+
+ if limit := metrics.GetMemory().GetHierarchicalMemoryLimit(); limit != 0 && limit != getCgroupV1NoLimit() {
+ return limit, nil
+ }
+
+ return 0, ErrNoLimit
+}
+
+func getCgroupV1NoLimit() uint64 {
+ ps := uint64(os.Getpagesize())
+ return math.MaxInt64 / ps * ps
+}
+
+// FromCgroupHybrid returns the memory limit from the cgroup v1 or v2.
+// It checks the cgroup v2 first, and if it fails, it falls back to cgroup v1.
+func FromCgroupHybrid() (uint64, error) {
+ limit, err := fromCgroupV2(filepath.Join(cgroupMountPoint, "unified"))
+ if err == nil {
+ return limit, nil
+ } else if err != ErrNoLimit {
+ return 0, err
+ }
+
+ return FromCgroupV1()
+}
+
+// FromCgroupV2 returns the memory limit from the cgroup v2.
+func FromCgroupV2() (uint64, error) {
+ return fromCgroupV2(cgroupMountPoint)
+}
+
+func fromCgroupV2(mountPoint string) (uint64, error) {
+ path, err := cgroup2.NestedGroupPath("")
+ if err != nil {
+ return 0, err
+ }
+
+ m, err := cgroup2.Load(path, cgroup2.WithMountpoint(mountPoint))
+ if err != nil {
+ return 0, err
+ }
+
+ stats, err := m.Stat()
+ if err != nil {
+ return 0, err
+ }
+
+ if limit := stats.GetMemory().GetUsageLimit(); limit != 0 && limit != math.MaxUint64 {
+ return limit, nil
+ }
+
+ return 0, ErrNoLimit
+}
diff --git a/vendor/github.com/KimMachineGun/automemlimit/memlimit/exp_system.go b/vendor/github.com/KimMachineGun/automemlimit/memlimit/exp_system.go
new file mode 100644
index 000000000..dee95f520
--- /dev/null
+++ b/vendor/github.com/KimMachineGun/automemlimit/memlimit/exp_system.go
@@ -0,0 +1,14 @@
+package memlimit
+
+import (
+ "github.com/pbnjay/memory"
+)
+
+// FromSystem returns the total memory of the system.
+func FromSystem() (uint64, error) {
+ limit := memory.TotalMemory()
+ if limit == 0 {
+ return 0, ErrNoLimit
+ }
+ return limit, nil
+}
diff --git a/vendor/github.com/KimMachineGun/automemlimit/memlimit/experiment.go b/vendor/github.com/KimMachineGun/automemlimit/memlimit/experiment.go
new file mode 100644
index 000000000..2a7c320ed
--- /dev/null
+++ b/vendor/github.com/KimMachineGun/automemlimit/memlimit/experiment.go
@@ -0,0 +1,59 @@
+package memlimit
+
+import (
+ "fmt"
+ "os"
+ "reflect"
+ "strings"
+)
+
+const (
+ envAUTOMEMLIMIT_EXPERIMENT = "AUTOMEMLIMIT_EXPERIMENT"
+)
+
+// Experiments is a set of experiment flags.
+// It is used to enable experimental features.
+//
+// You can set the flags by setting the environment variable AUTOMEMLIMIT_EXPERIMENT.
+// The value of the environment variable is a comma-separated list of experiment names.
+//
+// The following experiment names are known:
+//
+// - none: disable all experiments
+// - system: enable fallback to system memory limit
+type Experiments struct {
+ // System enables fallback to system memory limit.
+ System bool
+}
+
+func parseExperiments() (Experiments, error) {
+ var exp Experiments
+
+ // Create a map of known experiment names.
+ names := make(map[string]func(bool))
+ rv := reflect.ValueOf(&exp).Elem()
+ rt := rv.Type()
+ for i := 0; i < rt.NumField(); i++ {
+ field := rv.Field(i)
+ names[strings.ToLower(rt.Field(i).Name)] = field.SetBool
+ }
+
+ // Parse names.
+ for _, f := range strings.Split(os.Getenv(envAUTOMEMLIMIT_EXPERIMENT), ",") {
+ if f == "" {
+ continue
+ }
+ if f == "none" {
+ exp = Experiments{}
+ continue
+ }
+ val := true
+ set, ok := names[f]
+ if !ok {
+ return Experiments{}, fmt.Errorf("unknown AUTOMEMLIMIT_EXPERIMENT %s", f)
+ }
+ set(val)
+ }
+
+ return exp, nil
+}
diff --git a/vendor/github.com/KimMachineGun/automemlimit/memlimit/memlimit.go b/vendor/github.com/KimMachineGun/automemlimit/memlimit/memlimit.go
index dbb4d1c72..0d7a9853c 100644
--- a/vendor/github.com/KimMachineGun/automemlimit/memlimit/memlimit.go
+++ b/vendor/github.com/KimMachineGun/automemlimit/memlimit/memlimit.go
@@ -22,16 +22,11 @@ const (
var (
// ErrNoLimit is returned when the memory limit is not set.
ErrNoLimit = errors.New("memory is not limited")
- // ErrNoCgroup is returned when the process is not in cgroup.
- ErrNoCgroup = errors.New("process is not in cgroup")
- // ErrCgroupsNotSupported is returned when the system does not support cgroups.
- ErrCgroupsNotSupported = errors.New("cgroups is not supported on this system")
)
type config struct {
logger *log.Logger
ratio float64
- env bool
provider Provider
}
@@ -50,10 +45,10 @@ func WithRatio(ratio float64) Option {
// WithEnv configures whether to use environment variables.
//
// Default: false
+//
+// Deprecated: currently this does nothing.
func WithEnv() Option {
- return func(cfg *config) {
- cfg.env = true
- }
+ return func(cfg *config) {}
}
// WithProvider configures the provider.
@@ -65,17 +60,24 @@ func WithProvider(provider Provider) Option {
}
}
-// SetGoMemLimitWithOpts sets GOMEMLIMIT with options.
+// SetGoMemLimitWithOpts sets GOMEMLIMIT with options and environment variables.
+//
+// You can configure how much memory of the cgroup's memory limit to set as GOMEMLIMIT
+// through AUTOMEMLIMIT envrironment variable in the half-open range (0.0,1.0].
+//
+// If AUTOMEMLIMIT is not set, it defaults to 0.9. (10% is the headroom for memory sources the Go runtime is unaware of.)
+// If GOMEMLIMIT is already set or AUTOMEMLIMIT=off, this function does nothing.
+//
+// If AUTOMEMLIMIT_EXPERIMENT is set, it enables experimental features.
+// Please see the documentation of Experiments for more details.
//
// Options:
// - WithRatio
-// - WithEnv (see more SetGoMemLimitWithEnv)
// - WithProvider
func SetGoMemLimitWithOpts(opts ...Option) (_ int64, _err error) {
cfg := &config{
logger: log.New(io.Discard, "", log.LstdFlags),
ratio: defaultAUTOMEMLIMIT,
- env: false,
provider: FromCgroup,
}
if os.Getenv(envAUTOMEMLIMIT_DEBUG) == "true" {
@@ -90,6 +92,15 @@ func SetGoMemLimitWithOpts(opts ...Option) (_ int64, _err error) {
}
}()
+ exps, err := parseExperiments()
+ if err != nil {
+ return 0, fmt.Errorf("failed to parse experiments: %w", err)
+ }
+ if exps.System {
+ cfg.logger.Println("system experiment is enabled: using system memory limit as a fallback")
+ cfg.provider = ApplyFallback(cfg.provider, FromSystem)
+ }
+
snapshot := debug.SetMemoryLimit(-1)
defer func() {
err := recover()
@@ -122,6 +133,10 @@ func SetGoMemLimitWithOpts(opts ...Option) (_ int64, _err error) {
limit, err := setGoMemLimit(ApplyRatio(cfg.provider, ratio))
if err != nil {
+ if errors.Is(err, ErrNoLimit) {
+ cfg.logger.Printf("memory is not limited, skipping: %v\n", err)
+ return 0, nil
+ }
return 0, fmt.Errorf("failed to set GOMEMLIMIT: %w", err)
}
@@ -130,14 +145,8 @@ func SetGoMemLimitWithOpts(opts ...Option) (_ int64, _err error) {
return limit, nil
}
-// SetGoMemLimitWithEnv sets GOMEMLIMIT with the value from the environment variable.
-// You can configure how much memory of the cgroup's memory limit to set as GOMEMLIMIT
-// through AUTOMEMLIMIT in the half-open range (0.0,1.0].
-//
-// If AUTOMEMLIMIT is not set, it defaults to 0.9. (10% is the headroom for memory sources the Go runtime is unaware of.)
-// If GOMEMLIMIT is already set or AUTOMEMLIMIT=off, this function does nothing.
func SetGoMemLimitWithEnv() {
- _, _ = SetGoMemLimitWithOpts(WithEnv())
+ _, _ = SetGoMemLimitWithOpts()
}
// SetGoMemLimit sets GOMEMLIMIT with the value from the cgroup's memory limit and given ratio.