This is an automated email from the ASF dual-hosted git repository.

astefanutti pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-k.git

commit 22fe7285a8adb24159a970a9e0d57da78bb84813
Author: Antonin Stefanutti <anto...@stefanutti.fr>
AuthorDate: Fri Jan 24 16:31:16 2020 +0100

    feat(JVM): Max heap size heuristic based on container memory limit
---
 go.mod           |  1 +
 pkg/trait/jvm.go | 26 ++++++++++++++++++++++++++
 2 files changed, 27 insertions(+)

diff --git a/go.mod b/go.mod
index ac7aa1e..07f35d9 100644
--- a/go.mod
+++ b/go.mod
@@ -32,6 +32,7 @@ require (
        github.com/stoewer/go-strcase v1.0.2
        github.com/stretchr/testify v1.4.0
        go.uber.org/multierr v1.1.0
+       gopkg.in/inf.v0 v0.9.1
        gopkg.in/yaml.v2 v2.2.4
        k8s.io/api v0.0.0
        k8s.io/apimachinery v0.0.0
diff --git a/pkg/trait/jvm.go b/pkg/trait/jvm.go
index b1a783b..89f3710 100644
--- a/pkg/trait/jvm.go
+++ b/pkg/trait/jvm.go
@@ -22,9 +22,14 @@ import (
        "sort"
        "strings"
 
+       "gopkg.in/inf.v0"
+
        "github.com/pkg/errors"
        "github.com/scylladb/go-set/strset"
 
+       corev1 "k8s.io/api/core/v1"
+       "k8s.io/apimachinery/pkg/api/resource"
+
        k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
 
        v1 "github.com/apache/camel-k/pkg/apis/camel/v1"
@@ -125,11 +130,32 @@ func (t *jvmTrait) Apply(e *Environment) error {
                                        suspend, t.DebugAddress))
                }
 
+               hasHeapSizeOption := false
                // Add JVM options
                if t.Options != nil {
+                       hasHeapSizeOption = strings.Contains(*t.Options, 
"-Xmx") ||
+                               strings.Contains(*t.Options, "-XX:MaxHeapSize") 
||
+                               strings.Contains(*t.Options, 
"-XX:MinRAMPercentage") ||
+                               strings.Contains(*t.Options, 
"-XX:MaxRAMPercentage")
+
                        container.Args = append(container.Args, 
strings.Split(*t.Options, ",")...)
                }
 
+               // Tune JVM maximum heap size based on the container memory 
limit, if any.
+               // This is configured off-container, thus is limited to 
explicit user configuration.
+               // We may want to inject a wrapper script into the container 
image, so that it can
+               // be performed in-container, based on CGroups memory resource 
control files.
+               if memory, hasLimit := 
container.Resources.Limits[corev1.ResourceMemory]; !hasHeapSizeOption && 
hasLimit {
+                       // Simple heuristic that caps the maximum heap size to 
50% of the memory limit
+                       percentage := int64(50)
+                       // Unless the memory limit is lower than 300M, in which 
case we leave more room for the non-heap memory
+                       if resource.NewScaledQuantity(300, 6).Cmp(memory) > 0 {
+                               percentage = 25
+                       }
+                       memory.AsDec().Mul(memory.AsDec(), 
inf.NewDec(percentage, 2))
+                       container.Args = append(container.Args, 
fmt.Sprintf("-Xmx%dM", memory.ScaledValue(resource.Mega)))
+               }
+
                // Add mounted resources to the class path
                for _, m := range container.VolumeMounts {
                        classpath.Add(m.MountPath)

Reply via email to