diff options
author | Henning Baldersheim <balder@yahoo-inc.com> | 2022-09-29 16:24:26 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-09-29 16:24:26 +0200 |
commit | 32ae3685347015219dee34e6a2f5a3d3c14caab4 (patch) | |
tree | 3140c969c6ea8ee8bd4bb35510cc4fab4863d83a | |
parent | a4141f8564378037f2c1261a39ef6734e41eed79 (diff) | |
parent | 81a431c874b780fd7cfb38062e03c036c0895220 (diff) |
Merge pull request #24263 from vespa-engine/arnej/start-c-binary-5
Arnej/start c binary 5
-rw-r--r-- | client/go/script-utils/main.go | 7 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/cmd.go | 28 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/common_env.go | 67 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/execvp.go | 38 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/execvp_windows.go | 14 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/numactl.go | 8 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/numactl_test.go | 6 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/progspec.go | 56 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/setrlimit.go | 58 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/setrlimit_windows.go | 18 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/startcbinary.go | 37 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/tuning.go | 50 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/valgrind.go | 9 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/valgrind_test.go | 4 | ||||
-rw-r--r-- | client/go/script-utils/startcbinary/vespamalloc.go | 10 | ||||
-rw-r--r-- | client/go/util/io.go | 8 |
16 files changed, 362 insertions, 56 deletions
diff --git a/client/go/script-utils/main.go b/client/go/script-utils/main.go index 66fee5fba28..189140158ae 100644 --- a/client/go/script-utils/main.go +++ b/client/go/script-utils/main.go @@ -30,9 +30,7 @@ func main() { _ = vespa.FindHome() switch action { case "start-c-binary": - if !startcbinary.Run(os.Args[1:]) { - os.Exit(1) - } + os.Exit(startcbinary.Run(os.Args[1:])) case "export-env": vespa.ExportDefaultEnvToSh() case "security-env": @@ -59,6 +57,9 @@ func main() { cobra := clusterstate.NewSetNodeStateCmd() cobra.Execute() default: + if startcbinary.IsCandidate(os.Args[0]) { + os.Exit(startcbinary.Run(os.Args)) + } fmt.Fprintf(os.Stderr, "unknown action '%s'\n", action) fmt.Fprintln(os.Stderr, "actions: export-env, ipv6-only, security-env") fmt.Fprintln(os.Stderr, "(also: vespa-deploy, vespa-logfmt)") diff --git a/client/go/script-utils/startcbinary/cmd.go b/client/go/script-utils/startcbinary/cmd.go index 49bc2c8aedc..faa9a3fa595 100644 --- a/client/go/script-utils/startcbinary/cmd.go +++ b/client/go/script-utils/startcbinary/cmd.go @@ -4,21 +4,41 @@ package startcbinary import ( + "os" + "strings" + "github.com/vespa-engine/vespa/client/go/trace" + "github.com/vespa-engine/vespa/client/go/util" "github.com/vespa-engine/vespa/client/go/vespa" ) -func Run(args []string) bool { - trace.AdjustVerbosity(1) +func Run(args []string) int { + trace.AdjustVerbosity(0) if len(args) < 1 { trace.Warning("missing program argument") - return false + return 1 } spec := ProgSpec{ Program: args[0], - Args: args[1:], + Args: args, } spec.setup() vespa.LoadDefaultEnv() return startCbinary(spec) } + +func IsCandidate(program string) bool { + binary := program + "-bin" + if strings.Contains(binary, "/") { + return util.IsRegularFile(binary) + } else { + path := strings.Split(os.Getenv(ENV_PATH), ":") + for _, dir := range path { + fn := dir + "/" + binary + if util.IsRegularFile(fn) { + return true + } + } + } + return false +} diff --git a/client/go/script-utils/startcbinary/common_env.go b/client/go/script-utils/startcbinary/common_env.go index 908c61bb468..144a30b2ecb 100644 --- a/client/go/script-utils/startcbinary/common_env.go +++ b/client/go/script-utils/startcbinary/common_env.go @@ -5,34 +5,87 @@ package startcbinary import ( "os" + "strings" "github.com/vespa-engine/vespa/client/go/trace" + "github.com/vespa-engine/vespa/client/go/vespa" ) const ( ENV_LD_PRELOAD = "LD_PRELOAD" ENV_STD_THREAD_PREVENT_TRY_CATCH = "STD_THREAD_PREVENT_TRY_CATCH" ENV_GLIBCXX_FORCE_NEW = "GLIBCXX_FORCE_NEW" + ENV_JAVA_HOME = "JAVA_HOME" + ENV_LD_LIBRARY_PATH = "LD_LIBRARY_PATH" + ENV_MALLOC_ARENA_MAX = "MALLOC_ARENA_MAX" ENV_VESPA_AFFINITY_CPU_SOCKET = "VESPA_AFFINITY_CPU_SOCKET" ENV_VESPA_LOAD_CODE_AS_HUGEPAGES = "VESPA_LOAD_CODE_AS_HUGEPAGES" ENV_VESPA_MALLOC_HUGEPAGES = "VESPA_MALLOC_HUGEPAGES" ENV_VESPA_MALLOC_MADVISE_LIMIT = "VESPA_MALLOC_MADVISE_LIMIT" ENV_VESPA_NO_NUMACTL = "VESPA_NO_NUMACTL" + ENV_VESPA_TIMER_HZ = "VESPA_TIMER_HZ" + ENV_VESPA_USER = "VESPA_USER" ENV_VESPA_USE_HUGEPAGES = "VESPA_USE_HUGEPAGES" ENV_VESPA_USE_HUGEPAGES_LIST = "VESPA_USE_HUGEPAGES_LIST" ENV_VESPA_USE_MADVISE_LIST = "VESPA_USE_MADVISE_LIST" ENV_VESPA_USE_NO_VESPAMALLOC = "VESPA_USE_NO_VESPAMALLOC" ENV_VESPA_USE_VALGRIND = "VESPA_USE_VALGRIND" + ENV_VESPA_USE_VESPAMALLOC = "VESPA_USE_VESPAMALLOC" ENV_VESPA_USE_VESPAMALLOC_D = "VESPA_USE_VESPAMALLOC_D" ENV_VESPA_USE_VESPAMALLOC_DST = "VESPA_USE_VESPAMALLOC_DST" ENV_VESPA_VALGRIND_OPT = "VESPA_VALGRIND_OPT" + + // backwards compatibility variables: + ENV_HUGEPAGES_LIST = "HUGEPAGES_LIST" + ENV_MADVISE_LIST = "MADVISE_LIST" + ENV_NO_VESPAMALLOC_LIST = "NO_VESPAMALLOC_LIST" + ENV_PATH = "PATH" + ENV_ROOT = "ROOT" + ENV_VESPAMALLOCDST_LIST = "VESPAMALLOCDST_LIST" + ENV_VESPAMALLOCD_LIST = "VESPAMALLOCD_LIST" + ENV_VESPAMALLOC_LIST = "VESPAMALLOCD_LIST" ) +func (spec *ProgSpec) considerFallback(varName, varValue string) { + if spec.getenv(varName) == "" && varValue != "" { + spec.setenv(varName, varValue) + } +} + +func (spec *ProgSpec) considerEnvFallback(targetVar, fallbackVar string) { + spec.considerFallback(targetVar, spec.getenv(fallbackVar)) +} + func (spec *ProgSpec) configureCommonEnv() { os.Unsetenv(ENV_LD_PRELOAD) spec.setenv(ENV_STD_THREAD_PREVENT_TRY_CATCH, "true") spec.setenv(ENV_GLIBCXX_FORCE_NEW, "1") + spec.setenv(ENV_LD_LIBRARY_PATH, vespa.FindHome()+"/lib64") + spec.setenv(ENV_MALLOC_ARENA_MAX, "1") + + // fallback from old env.vars: + spec.considerEnvFallback(ENV_VESPA_USE_HUGEPAGES_LIST, ENV_HUGEPAGES_LIST) + spec.considerEnvFallback(ENV_VESPA_USE_MADVISE_LIST, ENV_MADVISE_LIST) + spec.considerEnvFallback(ENV_VESPA_USE_VESPAMALLOC, ENV_VESPAMALLOC_LIST) + spec.considerEnvFallback(ENV_VESPA_USE_VESPAMALLOC_D, ENV_VESPAMALLOCD_LIST) + spec.considerEnvFallback(ENV_VESPA_USE_VESPAMALLOC_DST, ENV_VESPAMALLOCDST_LIST) + spec.considerEnvFallback(ENV_VESPA_USE_NO_VESPAMALLOC, ENV_NO_VESPAMALLOC_LIST) + // other fallbacks: + spec.considerFallback(ENV_ROOT, vespa.FindHome()) + spec.considerFallback(ENV_VESPA_USER, vespa.FindVespaUser()) + spec.considerFallback(ENV_VESPA_USE_HUGEPAGES_LIST, "all") + spec.considerFallback(ENV_VESPA_USE_VESPAMALLOC, "all") + spec.considerFallback(ENV_VESPA_USE_NO_VESPAMALLOC, strings.Join([]string{ + "vespa-rpc-invoke", + "vespa-get-config", + "vespa-sentinel-cmd", + "vespa-route", + "vespa-proton-cmd", + "vespa-configproxy-cmd", + "vespa-config-status", + }, " ")) + } func (spec *ProgSpec) configureHugePages() { @@ -49,3 +102,17 @@ func (spec *ProgSpec) configureUseMadvise() { return } } + +func (spec *ProgSpec) configurePath() { + // Prefer newer gdb and pstack: + spec.prependPath("/opt/rh/gcc-toolset-11/root/usr/bin") + // Maven is needed for tester applications: + spec.prependPath(vespa.FindHome() + "/local/maven/bin") + spec.prependPath(vespa.FindHome() + "/bin64") + spec.prependPath(vespa.FindHome() + "/bin") + // how to find the "java" program? + // should be available in $VESPA_HOME/bin or JAVA_HOME + if javaHome := spec.getenv(ENV_JAVA_HOME); javaHome != "" { + spec.prependPath(javaHome + "/bin") + } +} diff --git a/client/go/script-utils/startcbinary/execvp.go b/client/go/script-utils/startcbinary/execvp.go new file mode 100644 index 00000000000..1ceaf88b47a --- /dev/null +++ b/client/go/script-utils/startcbinary/execvp.go @@ -0,0 +1,38 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Author: arnej + +//go:build !windows + +package startcbinary + +import ( + "fmt" + "os" + "strings" + + "github.com/vespa-engine/vespa/client/go/trace" + "github.com/vespa-engine/vespa/client/go/util" + "golang.org/x/sys/unix" +) + +func findInPath(prog string) string { + if strings.Contains(prog, "/") { + return prog + } + path := strings.Split(os.Getenv(ENV_PATH), ":") + for _, dir := range path { + fn := dir + "/" + prog + if util.IsRegularFile(fn) { + return fn + } + } + return prog +} + +func myexecvp(prog string, argv []string, envv []string) error { + trace.Trace("run cmd", strings.Join(argv, " ")) + prog = findInPath(prog) + argv[0] = prog + err := unix.Exec(prog, argv, envv) + return fmt.Errorf("cannot execute '%s': %v", prog, err) +} diff --git a/client/go/script-utils/startcbinary/execvp_windows.go b/client/go/script-utils/startcbinary/execvp_windows.go new file mode 100644 index 00000000000..f0642dcf9a0 --- /dev/null +++ b/client/go/script-utils/startcbinary/execvp_windows.go @@ -0,0 +1,14 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Author: arnej + +//go:build windows + +package startcbinary + +import ( + "fmt" +) + +func myexecvp(prog string, args []string, envv []string) error { + return fmt.Errorf("cannot execvp: %s", prog) +} diff --git a/client/go/script-utils/startcbinary/numactl.go b/client/go/script-utils/startcbinary/numactl.go index 6f49d8b8d9f..1456fe05a5f 100644 --- a/client/go/script-utils/startcbinary/numactl.go +++ b/client/go/script-utils/startcbinary/numactl.go @@ -5,7 +5,6 @@ package startcbinary import ( "fmt" - "os" "strconv" "strings" @@ -16,7 +15,7 @@ import ( func (p *ProgSpec) configureNumaCtl() { p.shouldUseNumaCtl = false p.numaSocket = -1 - if os.Getenv(ENV_VESPA_NO_NUMACTL) != "" { + if p.getenv(ENV_VESPA_NO_NUMACTL) != "" { return } backticks := util.BackTicksIgnoreStderr @@ -36,7 +35,7 @@ func (p *ProgSpec) configureNumaCtl() { return } p.shouldUseNumaCtl = true - if affinity := os.Getenv(ENV_VESPA_AFFINITY_CPU_SOCKET); affinity != "" { + if affinity := p.getenv(ENV_VESPA_AFFINITY_CPU_SOCKET); affinity != "" { wantSocket, _ := strconv.Atoi(affinity) trace.Debug("want socket:", wantSocket) parts := strings.Fields(out) @@ -57,7 +56,7 @@ func (p *ProgSpec) numaCtlBinary() string { return "numactl" } -func (p *ProgSpec) prependNumaCtl(program string, args []string) []string { +func (p *ProgSpec) prependNumaCtl(args []string) []string { result := make([]string, 0, 5+len(args)) result = append(result, "numactl") if p.numaSocket >= 0 { @@ -67,7 +66,6 @@ func (p *ProgSpec) prependNumaCtl(program string, args []string) []string { result = append(result, "--interleave") result = append(result, "all") } - result = append(result, program) for _, arg := range args { result = append(result, arg) } diff --git a/client/go/script-utils/startcbinary/numactl_test.go b/client/go/script-utils/startcbinary/numactl_test.go index a1d5586f57d..326ff088276 100644 --- a/client/go/script-utils/startcbinary/numactl_test.go +++ b/client/go/script-utils/startcbinary/numactl_test.go @@ -44,7 +44,7 @@ func TestNumaCtlDetection(t *testing.T) { spec.configureNumaCtl() assert.Equal(t, true, spec.shouldUseNumaCtl) assert.Equal(t, -1, spec.numaSocket) - argv = spec.prependNumaCtl("/bin/myprog", []string{"-c", "cfgid"}) + argv = spec.prependNumaCtl([]string{"/bin/myprog", "-c", "cfgid"}) trace.Trace("argv:", argv) assert.Equal(t, 6, len(argv)) assert.Equal(t, "numactl", argv[0]) @@ -56,7 +56,7 @@ func TestNumaCtlDetection(t *testing.T) { spec.configureNumaCtl() assert.Equal(t, true, spec.shouldUseNumaCtl) assert.Equal(t, 0, spec.numaSocket) - argv = spec.prependNumaCtl("/bin/myprog", []string{"-c", "cfgid", "-p", "param"}) + argv = spec.prependNumaCtl([]string{"/bin/myprog", "-c", "cfgid", "-p", "param"}) trace.Trace("argv:", argv) assert.Equal(t, 8, len(argv)) assert.Equal(t, "numactl", argv[0]) @@ -68,7 +68,7 @@ func TestNumaCtlDetection(t *testing.T) { spec.configureNumaCtl() assert.Equal(t, true, spec.shouldUseNumaCtl) assert.Equal(t, 1, spec.numaSocket) - argv = spec.prependNumaCtl("/bin/myprog", []string{}) + argv = spec.prependNumaCtl([]string{"/bin/myprog"}) trace.Trace("argv:", argv) assert.Equal(t, 4, len(argv)) assert.Equal(t, "numactl", argv[0]) diff --git a/client/go/script-utils/startcbinary/progspec.go b/client/go/script-utils/startcbinary/progspec.go index 614764e09e8..10097419395 100644 --- a/client/go/script-utils/startcbinary/progspec.go +++ b/client/go/script-utils/startcbinary/progspec.go @@ -39,8 +39,31 @@ func (p *ProgSpec) setenv(k, v string) { p.Env[k] = v } +func (p *ProgSpec) getenv(k string) string { + if v, ok := p.Env[k]; ok { + return v + } + return os.Getenv(k) +} + +func (p *ProgSpec) prependPath(dirName string) { + pathList := []string{dirName} + oldPath := p.getenv(ENV_PATH) + if oldPath == "" { + oldPath = "/usr/bin" + } + for _, part := range strings.Split(oldPath, ":") { + if part != dirName { + pathList = append(pathList, part) + } + } + newPath := strings.Join(pathList, ":") + p.setenv(ENV_PATH, newPath) + os.Setenv(ENV_PATH, newPath) +} + func (p *ProgSpec) matchesListEnv(envVarName string) bool { - return p.matchesListString(os.Getenv(envVarName)) + return p.matchesListString(p.getenv(envVarName)) } func (p *ProgSpec) matchesListString(env string) bool { @@ -60,11 +83,10 @@ func (p *ProgSpec) matchesListString(env string) bool { } func (p *ProgSpec) valueFromListEnv(envVarName string) string { - return p.valueFromListString(os.Getenv(envVarName)) + return p.valueFromListString(p.getenv(envVarName)) } func (p *ProgSpec) valueFromListString(env string) string { - parts := strings.Fields(env) for _, part := range parts { idx := strings.Index(part, "=") @@ -83,3 +105,31 @@ func (p *ProgSpec) valueFromListString(env string) string { } return "" } + +func (spec *ProgSpec) effectiveEnv() []string { + env := make(map[string]string) + for _, entry := range os.Environ() { + addInMap := func(kv string) bool { + for idx, elem := range kv { + if elem == '=' { + k := kv[:idx] + env[k] = kv + return true + } + } + return false + } + if !addInMap(entry) { + env[entry] = "" + } + } + for k, v := range spec.Env { + trace.Trace("add to environment:", k, "=", v) + env[k] = k + "=" + v + } + envv := make([]string, 0, len(env)) + for _, v := range env { + envv = append(envv, v) + } + return envv +} diff --git a/client/go/script-utils/startcbinary/setrlimit.go b/client/go/script-utils/startcbinary/setrlimit.go new file mode 100644 index 00000000000..5d7f33d5a0e --- /dev/null +++ b/client/go/script-utils/startcbinary/setrlimit.go @@ -0,0 +1,58 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +//go:build !windows + +package startcbinary + +import ( + "github.com/vespa-engine/vespa/client/go/trace" + "golang.org/x/sys/unix" + "os" +) + +type ResourceId int + +const ( + RLIMIT_CORE ResourceId = unix.RLIMIT_AS + RLIMIT_NOFILE ResourceId = unix.RLIMIT_NOFILE + RLIMIT_NPROC ResourceId = unix.RLIMIT_NPROC + NO_RLIMIT uint64 = ^uint64(0) +) + +func (rid ResourceId) String() string { + switch rid { + case RLIMIT_CORE: + return "core file size" + case RLIMIT_NOFILE: + return "open files" + case RLIMIT_NPROC: + return "max user processes" + } + return "unknown resource id" +} + +func setResourceLimit(resource ResourceId, newVal uint64) { + var current unix.Rlimit + err := unix.Getrlimit(int(resource), ¤t) + if err != nil { + trace.Warning("Could not get current resource limit:", err) + return + } + wanted := current + if current.Max < newVal { + if os.Getuid() == 0 { + wanted.Max = newVal + } else { + newVal = current.Max + } + } + if current.Cur < newVal { + wanted.Cur = newVal + } + err = unix.Setrlimit(int(resource), &wanted) + if err != nil { + trace.Trace("Failed setting resource limit:", err) + } else { + trace.Trace("Resource limit", resource, "adjusted OK:", wanted.Cur, "/", wanted.Max) + } +} diff --git a/client/go/script-utils/startcbinary/setrlimit_windows.go b/client/go/script-utils/startcbinary/setrlimit_windows.go new file mode 100644 index 00000000000..5bed1916246 --- /dev/null +++ b/client/go/script-utils/startcbinary/setrlimit_windows.go @@ -0,0 +1,18 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. + +//go:build windows + +package startcbinary + +type ResourceId int + +const ( + RLIMIT_CORE ResourceId = iota + RLIMIT_NOFILE + RLIMIT_NPROC + NO_RLIMIT uint64 = ^uint64(0) +) + +func setResourceLimit(resource ResourceId, max uint64) { + // nop +} diff --git a/client/go/script-utils/startcbinary/startcbinary.go b/client/go/script-utils/startcbinary/startcbinary.go index 56b0c9a1063..9c06ead4d06 100644 --- a/client/go/script-utils/startcbinary/startcbinary.go +++ b/client/go/script-utils/startcbinary/startcbinary.go @@ -6,13 +6,12 @@ package startcbinary import ( "fmt" "os" - "os/exec" - - "github.com/vespa-engine/vespa/client/go/trace" ) -func startCbinary(spec ProgSpec) bool { +func startCbinary(spec ProgSpec) int { spec.configureCommonEnv() + spec.configurePath() + spec.configureTuning() spec.configureValgrind() spec.configureNumaCtl() spec.configureHugePages() @@ -21,35 +20,25 @@ func startCbinary(spec ProgSpec) bool { err := spec.run() if err != nil { fmt.Fprintln(os.Stderr, err) + return 1 + } else { + return 0 } - return err == nil } func (spec *ProgSpec) run() error { prog := spec.Program + "-bin" args := spec.Args - cmd := exec.Command(prog, args...) if spec.shouldUseValgrind { - cmd.Path = spec.valgrindBinary() - cmd.Args = spec.prependValgrind(prog, args) + args = spec.prependValgrind(args) + prog = spec.valgrindBinary() } else if spec.shouldUseNumaCtl { - cmd.Path = spec.numaCtlBinary() - cmd.Args = spec.prependNumaCtl(prog, args) + args = spec.prependNumaCtl(args) + prog = spec.numaCtlBinary() } if spec.shouldUseVespaMalloc { - spec.setenv("LD_PRELOAD", spec.vespaMallocPreload) - } - if len(spec.Env) > 0 { - env := os.Environ() - for k, v := range spec.Env { - trace.Trace("add to environment:", k, "=", v) - env = append(env, k+"="+v) - } - cmd.Env = env + spec.setenv(ENV_LD_PRELOAD, spec.vespaMallocPreload) } - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - trace.Trace("run cmd", cmd) - return cmd.Run() + envv := spec.effectiveEnv() + return myexecvp(prog, args, envv) } diff --git a/client/go/script-utils/startcbinary/tuning.go b/client/go/script-utils/startcbinary/tuning.go new file mode 100644 index 00000000000..80fec7cc6c2 --- /dev/null +++ b/client/go/script-utils/startcbinary/tuning.go @@ -0,0 +1,50 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +// Author: arnej + +package startcbinary + +import ( + "os" + "strconv" + "strings" + + "github.com/vespa-engine/vespa/client/go/trace" + "github.com/vespa-engine/vespa/client/go/util" +) + +func (spec *ProgSpec) optionallyReduceBaseFrequency() { + if spec.getenv(ENV_VESPA_TIMER_HZ) == "" { + backticks := util.BackTicksIgnoreStderr + out, _ := backticks.Run("uname", "-r") + if strings.Contains(out, "linuxkit") { + trace.Trace("Running docker on macos. Reducing base frequency from 1000hz to 100hz due to high cost of sampling time. This will reduce timeout accuracy.") + spec.setenv(ENV_VESPA_TIMER_HZ, "100") + } + } +} + +func getThpSizeMb() int { + const fn = "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size" + thp_size := 2 + line, err := os.ReadFile(fn) + if err == nil { + chomped := strings.TrimSuffix(string(line), "\n") + number, err := strconv.Atoi(chomped) + if err == nil { + thp_size = number / (1024 * 1024) + trace.Trace("thp_size", chomped, "=>", thp_size) + } else { + trace.Trace("no thp_size:", err) + } + } else { + trace.Trace("no thp_size:", err) + } + return thp_size +} + +func (spec *ProgSpec) configureTuning() { + spec.optionallyReduceBaseFrequency() + setResourceLimit(RLIMIT_CORE, NO_RLIMIT) + setResourceLimit(RLIMIT_NOFILE, 262144) + setResourceLimit(RLIMIT_NPROC, 409600) +} diff --git a/client/go/script-utils/startcbinary/valgrind.go b/client/go/script-utils/startcbinary/valgrind.go index fb47fa36e9b..f474347016d 100644 --- a/client/go/script-utils/startcbinary/valgrind.go +++ b/client/go/script-utils/startcbinary/valgrind.go @@ -16,7 +16,7 @@ import ( func (p *ProgSpec) configureValgrind() { p.shouldUseValgrind = false p.shouldUseCallgrind = false - env := os.Getenv(ENV_VESPA_USE_VALGRIND) + env := p.getenv(ENV_VESPA_USE_VALGRIND) parts := strings.Split(env, " ") for _, part := range parts { if p.BaseName == part { @@ -27,7 +27,7 @@ func (p *ProgSpec) configureValgrind() { trace.Trace("no valgrind, 'which' fails:", err, "=>", out) return } - if opts := os.Getenv(ENV_VESPA_VALGRIND_OPT); strings.Contains(opts, "callgrind") { + if opts := p.getenv(ENV_VESPA_VALGRIND_OPT); strings.Contains(opts, "callgrind") { p.shouldUseCallgrind = true } p.shouldUseValgrind = true @@ -42,7 +42,7 @@ func (p *ProgSpec) valgrindBinary() string { } func (p *ProgSpec) valgrindOptions() []string { - env := os.Getenv(ENV_VESPA_VALGRIND_OPT) + env := p.getenv(ENV_VESPA_VALGRIND_OPT) if env != "" { return strings.Fields(env) } @@ -71,14 +71,13 @@ func (p *ProgSpec) valgrindLogOption() string { return fmt.Sprintf("--log-file=%s/tmp/valgrind.%s.log.%d", vespa.FindHome(), p.BaseName, os.Getpid()) } -func (p *ProgSpec) prependValgrind(program string, args []string) []string { +func (p *ProgSpec) prependValgrind(args []string) []string { result := make([]string, 0, 15+len(args)) result = append(result, p.valgrindBinary()) for _, arg := range p.valgrindOptions() { result = append(result, arg) } result = append(result, p.valgrindLogOption()) - result = append(result, program) for _, arg := range args { result = append(result, arg) } diff --git a/client/go/script-utils/startcbinary/valgrind_test.go b/client/go/script-utils/startcbinary/valgrind_test.go index 6c01945a828..906dfc054c6 100644 --- a/client/go/script-utils/startcbinary/valgrind_test.go +++ b/client/go/script-utils/startcbinary/valgrind_test.go @@ -63,7 +63,7 @@ func TestValgrindDetection(t *testing.T) { assert.Equal(t, true, spec.shouldUseValgrind) assert.Equal(t, false, spec.shouldUseCallgrind) - argv = spec.prependValgrind("/bin/myprog", []string{"-c", "cfgid"}) + argv = spec.prependValgrind([]string{"/bin/myprog", "-c", "cfgid"}) trace.Trace("argv:", argv) assert.Equal(t, 11, len(argv)) assert.Equal(t, "valgrind", argv[0]) @@ -79,7 +79,7 @@ func TestValgrindDetection(t *testing.T) { assert.Equal(t, true, spec.shouldUseValgrind) assert.Equal(t, true, spec.shouldUseCallgrind) - argv = spec.prependValgrind("/bin/myprog", []string{"-c", "cfgid"}) + argv = spec.prependValgrind([]string{"/bin/myprog", "-c", "cfgid"}) trace.Trace("argv:", argv) assert.Equal(t, 6, len(argv)) assert.Equal(t, "valgrind", argv[0]) diff --git a/client/go/script-utils/startcbinary/vespamalloc.go b/client/go/script-utils/startcbinary/vespamalloc.go index 7105f4b5562..15b0fdc80bc 100644 --- a/client/go/script-utils/startcbinary/vespamalloc.go +++ b/client/go/script-utils/startcbinary/vespamalloc.go @@ -5,7 +5,6 @@ package startcbinary import ( "fmt" - "os" "github.com/vespa-engine/vespa/client/go/trace" "github.com/vespa-engine/vespa/client/go/vespa" @@ -29,6 +28,7 @@ func (p *ProgSpec) configureVespaMalloc() { p.shouldUseVespaMalloc = false if p.matchesListEnv(ENV_VESPA_USE_NO_VESPAMALLOC) { trace.Trace("use no vespamalloc:", p.BaseName) + return } if p.shouldUseValgrind && !p.shouldUseCallgrind { trace.Trace("use valgrind, so no vespamalloc:", p.BaseName) @@ -39,20 +39,18 @@ func (p *ProgSpec) configureVespaMalloc() { useFile = vespaMallocLib("libvespamallocdst16.so") } else if p.matchesListEnv(ENV_VESPA_USE_VESPAMALLOC_D) { useFile = vespaMallocLib("libvespamallocd.so") - } else { + } else if p.matchesListEnv(ENV_VESPA_USE_VESPAMALLOC) { useFile = vespaMallocLib("libvespamalloc.so") } trace.Trace("use file:", useFile) if useFile == "" { return } - if loadAsHuge := os.Getenv(ENV_VESPA_LOAD_CODE_AS_HUGEPAGES); loadAsHuge != "" { + if loadAsHuge := p.getenv(ENV_VESPA_LOAD_CODE_AS_HUGEPAGES); loadAsHuge != "" { otherFile := vespaMallocLib("libvespa_load_as_huge.so") useFile = fmt.Sprintf("%s:%s", useFile, otherFile) } - if useHugePages := os.Getenv(ENV_VESPA_USE_HUGEPAGES); useHugePages != "" { - p.setenv(ENV_VESPA_MALLOC_HUGEPAGES, useHugePages) - } + p.considerEnvFallback(ENV_VESPA_MALLOC_HUGEPAGES, ENV_VESPA_USE_HUGEPAGES) p.vespaMallocPreload = useFile p.shouldUseVespaMalloc = true } diff --git a/client/go/util/io.go b/client/go/util/io.go index 68e855b0c3e..89f14c1a643 100644 --- a/client/go/util/io.go +++ b/client/go/util/io.go @@ -20,12 +20,18 @@ func PathExists(path string) bool { return !errors.Is(err, os.ErrNotExist) } -// Returns true is the given path points to an existing directory +// Returns true if the given path points to an existing directory func IsDirectory(path string) bool { info, err := os.Stat(path) return !errors.Is(err, os.ErrNotExist) && info.IsDir() } +// Returns true if the given path points to an existing file +func IsRegularFile(path string) bool { + info, err := os.Stat(path) + return !errors.Is(err, os.ErrNotExist) && info.Mode().IsRegular() +} + // Returns the content of a reader as a string func ReaderToString(reader io.Reader) string { var buffer strings.Builder |