diff options
author | Arne Juul <arnej@yahooinc.com> | 2022-11-09 09:00:53 +0000 |
---|---|---|
committer | Arne Juul <arnej@yahooinc.com> | 2022-11-09 09:36:46 +0000 |
commit | 29043ae1e3e79ca3587d2311d0276dba0979a406 (patch) | |
tree | e82de066a5e0a51865e950c96ddc41f446f95bda | |
parent | bccc424f69dc1748813bc3d3b5f87fdc9ba1ed16 (diff) |
use new memory abstraction
-rw-r--r-- | client/go/jvm/application_container.go | 12 | ||||
-rw-r--r-- | client/go/jvm/mem_avail.go | 22 | ||||
-rw-r--r-- | client/go/jvm/mem_options.go | 80 | ||||
-rw-r--r-- | client/go/jvm/mem_options_test.go | 15 | ||||
-rw-r--r-- | client/go/jvm/options_test.go | 63 |
5 files changed, 94 insertions, 98 deletions
diff --git a/client/go/jvm/application_container.go b/client/go/jvm/application_container.go index 081dc96c5a4..14efbe65e33 100644 --- a/client/go/jvm/application_container.go +++ b/client/go/jvm/application_container.go @@ -74,6 +74,10 @@ func (a *ApplicationContainer) addJdiscProperties() { } +func validPercentage(val int) bool { + return val > 0 && val < 100 +} + func (a *ApplicationContainer) configureMemory(qc *QrStartConfig) { jvm_heapsize := qc.Jvm.Heapsize // Heap size (in megabytes) for the Java VM jvm_minHeapsize := qc.Jvm.MinHeapsize // Min heapsize (in megabytes) for the Java VM @@ -90,10 +94,10 @@ func (a *ApplicationContainer) configureMemory(qc *QrStartConfig) { if jvm_minHeapsize <= 0 { jvm_minHeapsize = jvm_heapsize } - available := getAvailableMbOfMemory() - if jvm_heapSizeAsPercentageOfPhysicalMemory > 0 && jvm_heapSizeAsPercentageOfPhysicalMemory < 100 && available > 0 { + available := getAvailableMemory() + if validPercentage(jvm_heapSizeAsPercentageOfPhysicalMemory) && available.ToMB() > 500 { available = adjustAvailableMemory(available) - jvm_heapsize = available * jvm_heapSizeAsPercentageOfPhysicalMemory / 100 + jvm_heapsize = available.ToMB() * jvm_heapSizeAsPercentageOfPhysicalMemory / 100 } if jvm_minHeapsize > jvm_heapsize { trace.Warning(fmt.Sprintf( @@ -119,7 +123,7 @@ func (a *ApplicationContainer) configureMemory(qc *QrStartConfig) { opts.AddOption(fmt.Sprintf("-Xmx%dm", jvm_heapsize)) opts.AddOption(fmt.Sprintf("-XX:ThreadStackSize=%d", jvm_stacksize)) opts.AddOption(fmt.Sprintf("-XX:MaxDirectMemorySize=%dm", maxDirectMemorySize)) - opts.MaybeAddHugepages(jvm_heapsize) + opts.MaybeAddHugepages(MegaBytesOfMemory(jvm_heapsize)) if jvm_compressedClassSpaceSize > 0 { opts.AddOption(fmt.Sprintf("-XX:CompressedClassSpaceSize=%dm", jvm_compressedClassSpaceSize)) } diff --git a/client/go/jvm/mem_avail.go b/client/go/jvm/mem_avail.go index 4447bd8d2f0..78627a9b7bb 100644 --- a/client/go/jvm/mem_avail.go +++ b/client/go/jvm/mem_avail.go @@ -13,19 +13,19 @@ import ( "github.com/vespa-engine/vespa/client/go/util" ) -func parseFree(txt string) int { +func parseFree(txt string) AmountOfMemory { f := strings.Fields(txt) for idx, field := range f { if field == "Mem:" && idx+1 < len(f) { res, err := strconv.Atoi(f[idx+1]) if err == nil { - return res + return MegaBytesOfMemory(res) } else { trace.Warning(err) } } } - return 0 + return BytesOfMemory(0) } func parentDir(dir string) string { @@ -74,8 +74,8 @@ func vespa_cg2get(filename string) (output string, err error) { return min_value, nil } -func getAvailableMbOfMemory() int { - result := 0 +func getAvailableMemory() AmountOfMemory { + result := BytesOfMemory(0) backticks := util.BackTicksWithStderr freeOutput, err := backticks.Run("free", "-m") if err == nil { @@ -84,7 +84,7 @@ func getAvailableMbOfMemory() int { } else { trace.Trace("run 'free' failed:", err) } - available_cgroup := int(1 << 31) + available_cgroup := KiloBytesOfMemory(1 << 31) cggetOutput, err := backticks.Run("cgget", "-nv", "-r", "memory.limit_in_bytes", "/") if err != nil { if strings.Contains(cggetOutput, "Cgroup is not mounted") { @@ -96,16 +96,16 @@ func getAvailableMbOfMemory() int { trace.Debug("run 'cgget' failed:", err, "=>", cggetOutput) } if err == nil && cggetOutput != "max" { - numBytes, err := strconv.Atoi(cggetOutput) - if err == nil && numBytes > PowerOfTwo10 { - available_cgroup = numBytes / PowerOfTwo10 + numBytes, err := strconv.ParseInt(cggetOutput, 10, 64) + if err == nil && numBytes > (1<<28) { + available_cgroup = AmountOfMemory{numBytes: numBytes} } else { trace.Warning("unexpected 'cgget' output:", cggetOutput) } } - if result == 0 || result > available_cgroup { + if result.ToKB() == 0 || result.ToKB() > available_cgroup.ToKB() { result = available_cgroup } - trace.Trace("getAvailableMbOfMemory returns:", result) + trace.Trace("getAvailableMemory returns:", result) return result } diff --git a/client/go/jvm/mem_options.go b/client/go/jvm/mem_options.go index 4c708bc526a..a2be6ac7b26 100644 --- a/client/go/jvm/mem_options.go +++ b/client/go/jvm/mem_options.go @@ -11,77 +11,59 @@ import ( "github.com/vespa-engine/vespa/client/go/util" ) -const ( - PowerOfTwo10 = 1 << 10 -) - -func (opts *Options) getOrSetHeapMb(prefix string, heapMb int) int { +func (opts *Options) getOrSetHeapSize(prefix string, heapSize AmountOfMemory) AmountOfMemory { var missing bool = true for _, x := range opts.jvmArgs { if strings.HasPrefix(x, prefix) { - var val int - var suffix rune - n, err := fmt.Sscanf(x, prefix+"%d%c", &val, &suffix) - if n == 2 && err == nil { + val, err := ParseJvmMemorySpec(strings.TrimPrefix(x, prefix)) + if err == nil { missing = false - switch suffix { - case 'k': - heapMb = val / PowerOfTwo10 - case 'm': - heapMb = val - case 'g': - heapMb = val * PowerOfTwo10 - default: - missing = true - } + heapSize = val } } } if missing { - suffix := "m" - newVal := heapMb - if (newVal % PowerOfTwo10) == 0 { - suffix = "g" - newVal /= PowerOfTwo10 - } - opts.AppendOption(fmt.Sprintf("%s%d%s", prefix, newVal, suffix)) + opts.AppendOption(fmt.Sprintf("%s%s", prefix, heapSize.AsJvmSpec())) } - return heapMb + return heapSize } -func (opts *Options) CurMinHeapMb(fallback int) int { - return opts.getOrSetHeapMb("-Xms", fallback) +func (opts *Options) CurMinHeapSize(fallback AmountOfMemory) AmountOfMemory { + return opts.getOrSetHeapSize("-Xms", fallback) } -func (opts *Options) CurMaxHeapMb(fallback int) int { - return opts.getOrSetHeapMb("-Xmx", fallback) +func (opts *Options) CurMaxHeapSize(fallback AmountOfMemory) AmountOfMemory { + return opts.getOrSetHeapSize("-Xmx", fallback) } -func (opts *Options) AddDefaultHeapSizeArgs(minHeapMb, maxHeapMb int) { - trace.Trace("AddDefaultHeapSizeArgs", minHeapMb, "/", maxHeapMb) - minHeapMb = opts.CurMinHeapMb(minHeapMb) - maxHeapMb = opts.CurMaxHeapMb(maxHeapMb) - opts.MaybeAddHugepages(maxHeapMb) +func (opts *Options) AddDefaultHeapSizeArgs(minHeapSize, maxHeapSize AmountOfMemory) { + trace.Trace("AddDefaultHeapSizeArgs", minHeapSize, "/", maxHeapSize) + minHeapSize = opts.CurMinHeapSize(minHeapSize) + maxHeapSize = opts.CurMaxHeapSize(maxHeapSize) + opts.MaybeAddHugepages(maxHeapSize) } -func (opts *Options) MaybeAddHugepages(maxHeapMb int) { - thpSizeMb := util.GetThpSizeMb() - if thpSizeMb*2 < maxHeapMb { - trace.Trace("add UseTransparentHugePages, thpSize", thpSizeMb, "* 2 < maxHeap", maxHeapMb) +func (opts *Options) MaybeAddHugepages(maxHeapSize AmountOfMemory) { + thpSizeSize := util.GetThpSizeMb() + heapSize := maxHeapSize.ToMB() + if thpSizeSize*2 < heapSize { + trace.Trace("add UseTransparentHugePages, thpSize", thpSizeSize, "* 2 < maxHeap", heapSize) opts.AddOption("-XX:+UseTransparentHugePages") } else { - trace.Trace("no UseTransparentHugePages, thpSize", thpSizeMb, "* 2 >= maxHeap", maxHeapMb) + trace.Trace("no UseTransparentHugePages, thpSize", thpSizeSize, "* 2 >= maxHeap", heapSize) } } -func adjustAvailableMemory(measured int) int { - reserved := 1024 - need_min := 64 - if measured > need_min+2*reserved { - return measured - reserved +func adjustAvailableMemory(measured AmountOfMemory) AmountOfMemory { + reserved := 1024 // MB + need_min := 64 // MB + available := measured.ToMB() + if available > need_min+2*reserved { + return MegaBytesOfMemory(available - reserved) } - if measured > need_min { - return (measured + need_min) / 2 + if available > need_min { + adjusted := (available + need_min) / 2 + return MegaBytesOfMemory(adjusted) } - return need_min + return MegaBytesOfMemory(need_min) } diff --git a/client/go/jvm/mem_options_test.go b/client/go/jvm/mem_options_test.go index 80ab588c8dc..d7bb05000ca 100644 --- a/client/go/jvm/mem_options_test.go +++ b/client/go/jvm/mem_options_test.go @@ -11,11 +11,12 @@ import ( func TestAdjustment(t *testing.T) { lastAdj := 64 for i := 0; i < 4096; i++ { - adj := adjustAvailableMemory(i) - assert.True(t, adj >= lastAdj) - lastAdj = adj + adj := adjustAvailableMemory(MegaBytesOfMemory(i)).ToMB() + assert.True(t, int(adj) >= lastAdj) + lastAdj = int(adj) } - assert.Equal(t, 30000, adjustAvailableMemory(31024)) + adj := adjustAvailableMemory(MegaBytesOfMemory(31024)).ToMB() + assert.Equal(t, 30000, int(adj)) } func TestParseFree(t *testing.T) { @@ -24,11 +25,11 @@ func TestParseFree(t *testing.T) { Mem: 19986 656 3157 218 16172 18832 Swap: 2047 320 1727 `) - assert.Equal(t, 19986, res) + assert.Equal(t, MegaBytesOfMemory(19986), res) } func TestGetAvail(t *testing.T) { trace.AdjustVerbosity(0) - available := getAvailableMbOfMemory() - assert.True(t, available >= 0) + available := getAvailableMemory() + assert.True(t, available.ToMB() >= 0) } diff --git a/client/go/jvm/options_test.go b/client/go/jvm/options_test.go index c451b87ff24..99b6e8dd6f3 100644 --- a/client/go/jvm/options_test.go +++ b/client/go/jvm/options_test.go @@ -7,60 +7,69 @@ import ( "github.com/stretchr/testify/assert" ) -const ( - aa = 123 - bb = 234 - cc = 456 - dd = 567 - ee = 16 * PowerOfTwo10 - ff = 31 * PowerOfTwo10 -) - -func TestHeapMbSimple(t *testing.T) { +func TestHeapSizeSimple(t *testing.T) { + var ( + aa = MegaBytesOfMemory(123) + bb = MegaBytesOfMemory(234) + ) o := NewOptions(NewStandaloneContainer("foo")) - assert.Equal(t, aa, o.CurMinHeapMb(aa)) - assert.Equal(t, bb, o.CurMaxHeapMb(bb)) + assert.Equal(t, aa, o.CurMinHeapSize(aa)) + assert.Equal(t, bb, o.CurMaxHeapSize(bb)) assert.Equal(t, 2, len(o.jvmArgs)) assert.Equal(t, "-Xms123m", o.jvmArgs[0]) assert.Equal(t, "-Xmx234m", o.jvmArgs[1]) } -func TestHeapMbMulti(t *testing.T) { +func TestHeapSizeMulti(t *testing.T) { + var ( + aa = MegaBytesOfMemory(123) + bb = MegaBytesOfMemory(234) + cc = MegaBytesOfMemory(456) + dd = MegaBytesOfMemory(567) + ) o := NewOptions(NewStandaloneContainer("foo")) - assert.Equal(t, aa, o.CurMinHeapMb(aa)) - assert.Equal(t, aa, o.CurMaxHeapMb(aa)) + assert.Equal(t, aa, o.CurMinHeapSize(aa)) + assert.Equal(t, aa, o.CurMaxHeapSize(aa)) assert.Equal(t, 2, len(o.jvmArgs)) o.AppendOption("-Xms234m") o.AppendOption("-Xmx456m") assert.Equal(t, 4, len(o.jvmArgs)) - assert.Equal(t, bb, o.CurMinHeapMb(aa)) - assert.Equal(t, bb, o.CurMinHeapMb(dd)) - assert.Equal(t, cc, o.CurMaxHeapMb(aa)) - assert.Equal(t, cc, o.CurMaxHeapMb(dd)) + assert.Equal(t, bb, o.CurMinHeapSize(aa)) + assert.Equal(t, bb, o.CurMinHeapSize(dd)) + assert.Equal(t, cc, o.CurMaxHeapSize(aa)) + assert.Equal(t, cc, o.CurMaxHeapSize(dd)) o.AppendOption("-Xms1g") o.AppendOption("-Xmx2g") - assert.Equal(t, 1*PowerOfTwo10, o.CurMinHeapMb(aa)) - assert.Equal(t, 2*PowerOfTwo10, o.CurMaxHeapMb(aa)) + assert.Equal(t, GigaBytesOfMemory(1), o.CurMinHeapSize(aa)) + assert.Equal(t, GigaBytesOfMemory(2), o.CurMaxHeapSize(aa)) o.AppendOption("-Xms16777216k") o.AppendOption("-Xmx32505856k") - assert.Equal(t, ee, o.CurMinHeapMb(aa)) - assert.Equal(t, ff, o.CurMaxHeapMb(aa)) + assert.Equal(t, KiloBytesOfMemory(16777216), o.CurMinHeapSize(aa)) + assert.Equal(t, KiloBytesOfMemory(32505856), o.CurMaxHeapSize(aa)) } -func TestHeapMbAdd(t *testing.T) { +func TestHeapSizeAdd(t *testing.T) { + var ( + gg = MegaBytesOfMemory(12345) + hh = MegaBytesOfMemory(23456) + ) o := NewOptions(NewStandaloneContainer("foo")) - o.AddDefaultHeapSizeArgs(12345, 23456) + o.AddDefaultHeapSizeArgs(gg, hh) assert.Equal(t, 3, len(o.jvmArgs)) assert.Equal(t, "-Xms12345m", o.jvmArgs[0]) assert.Equal(t, "-Xmx23456m", o.jvmArgs[1]) assert.Equal(t, "-XX:+UseTransparentHugePages", o.jvmArgs[2]) } -func TestHeapMbNoAdd(t *testing.T) { +func TestHeapSizeNoAdd(t *testing.T) { + var ( + bb = MegaBytesOfMemory(234) + cc = MegaBytesOfMemory(456) + ) o := NewOptions(NewStandaloneContainer("foo")) o.AppendOption("-Xms128k") o.AppendOption("-Xmx1280k") - o.AddDefaultHeapSizeArgs(234, 345) + o.AddDefaultHeapSizeArgs(bb, cc) assert.Equal(t, 2, len(o.jvmArgs)) assert.Equal(t, "-Xms128k", o.jvmArgs[0]) assert.Equal(t, "-Xmx1280k", o.jvmArgs[1]) |