├── README.md
├── dist
├── README.txt
└── app.jar
├── images
└── elastic-duke-70x70.png
├── kubernetes
├── README.md
├── dashboards
│ ├── java-dashboard-cpu.json
│ └── java-dashboard-mem.json
├── deployments
│ ├── adoptopenjdk.yaml
│ ├── deployment.yaml
│ ├── dragonwell.yaml
│ ├── libericajdk12.yaml
│ ├── openj9.yaml
│ ├── openjdk13.yaml
│ └── zing.yaml
├── images
│ └── kube.png
├── java-dashboard-cpu.json
├── java-dashboard-mem.json
├── manifests
│ ├── actions.jps
│ ├── manifest-k8s-dragonwell-g1.yaml
│ ├── manifest-k8s-openj9.yaml
│ ├── manifest-k8s-zgc.yaml
│ └── manifest-k8s-zing.yaml
└── scripts
│ ├── grafana.sh
│ ├── label-nodes.sh
│ └── labelnodes.sh
├── manifest-k8s.yaml
├── manifest.yml
└── src
└── com
└── jelastic
└── verticalscaling
├── Load.java
├── MemoryUsage.java
└── Test.java
/README.md:
--------------------------------------------------------------------------------
1 | # Java Vertical Scaling Load Test
2 | A simple app for testing JVM vertical scaling
3 |
4 |
5 | ``` java [$JAVA_OPTS] -jar app.jar [sleep] ```
6 |
7 | * $JAVA_OPTS - JVM start options, for example -Xmx2g -Xms32m -XX:+UseG1GC
8 | * sleep - interval between memory load cycles in milliseconds, default is 10ms
9 |
10 |
11 | Press \ to start the load test!
12 |
--------------------------------------------------------------------------------
/dist/README.txt:
--------------------------------------------------------------------------------
1 | ========================
2 | BUILD OUTPUT DESCRIPTION
3 | ========================
4 |
5 | When you build an Java application project that has a main class, the IDE
6 | automatically copies all of the JAR
7 | files on the projects classpath to your projects dist/lib folder. The IDE
8 | also adds each of the JAR files to the Class-Path element in the application
9 | JAR files manifest file (MANIFEST.MF).
10 |
11 | To run the project from the command line, go to the dist folder and
12 | type the following:
13 |
14 | java -jar "app.jar"
15 |
16 | To distribute this project, zip up the dist folder (including the lib folder)
17 | and distribute the ZIP file.
18 |
19 | Notes:
20 |
21 | * If two JAR files on the project classpath have the same name, only the first
22 | JAR file is copied to the lib folder.
23 | * Only JAR files are copied to the lib folder.
24 | If the classpath contains other types of files or folders, these files (folders)
25 | are not copied.
26 | * If a library on the projects classpath also has a Class-Path element
27 | specified in the manifest,the content of the Class-Path element has to be on
28 | the projects runtime path.
29 | * To set a main class in a standard Java project, right-click the project node
30 | in the Projects window and choose Properties. Then click Run and enter the
31 | class name in the Main Class field. Alternatively, you can manually type the
32 | class name in the manifest Main-Class element.
33 |
--------------------------------------------------------------------------------
/dist/app.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/6cfdd3c9f4561c00f7b1bd8f03228d3be64145c6/dist/app.jar
--------------------------------------------------------------------------------
/images/elastic-duke-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/6cfdd3c9f4561c00f7b1bd8f03228d3be64145c6/images/elastic-duke-70x70.png
--------------------------------------------------------------------------------
/kubernetes/README.md:
--------------------------------------------------------------------------------
1 | # Java vertical scaling test
2 |
3 | ## Nodes
4 |
5 | This addon assumes that there are 6 nodes in the cluster. Nodes are [labeled](https://github.com/bianchi2/kube-deployer/blob/master/scripts/labelnodes.sh) in a special way so that Kubernetes schedules 1 Java pod per node.
6 | Currently, the addon does not check if there are enough nodes, so if nodes count is under 6, one of the pods won't be scheduled.
7 |
8 | Also, Jelastic nodes displayNames are modified to make statistics analysis simpler.
9 |
10 |
11 | ## Deployments
12 |
13 | This addon creates 6 K8s deployments in `java` namespace. Deployments are defined in .yaml files and can be edited if necessary.
14 |
15 | The addon processes retrieved yamls and replaces placeholders with desired values (at this moment only memory limits and JAVA_OPTS).
16 | You can make more things configurable is necessary.
17 |
18 | ```
19 | curl ${baseUrl}/deployments/adoptopenjdk.yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.adoptopenjdk}/g" | sed "s/%MEM_LIMIT%/${settings.adoptopenjdkLimit}/g" | kubectl apply -f -
20 | ```
21 |
22 | ## Memory Limits
23 |
24 | The default memory limit is `3Gi`. You can change it for each pod in `${settings.jdkFlavor}`:
25 |
26 | ```
27 | - type: string
28 | name: zulujdkLimit
29 | caption: Zulu Pod Mem Limit
30 | default: 3Gi
31 | inputType: hidden
32 | ```
33 | Remove `inputType: hidden` if you want to be able to define memory requests for containers on UI.
34 |
35 | ## JAVA_OPTS
36 |
37 | There are common `JAVA_OPTS` defined in `{globals.common}` and `JAVA_OPTS` defined for each individual pod - `$globals.jdkFlavor`
38 |
39 | ```
40 | globals:
41 | common: -Xmx3g -Xms32m -XX:+UseCompressedOops
42 | zing: -XX:-AutoTuneResourceDefaultsBasedOnXmx
43 | openjdk: -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZUncommitDelay=1 -XX:ZCollectionInterval=30
44 | openj9: -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=1 -Xjit:waitTimeToEnterDeepIdleMode=1000
45 | adoptopenjdk: -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
46 | liberica: -XX:+UseG1GC -XX:G1PeriodicGCInterval=10k
47 | zulujdk: -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
48 | ```
49 |
50 | ## Redeploy
51 |
52 | When this addon is repeatedly applied to a Kubernetes cluster, all existing deployments in `java` namespace are forcefully deleted,
53 | thus, there is no need to manually clean up resources before a repeated deployment.
54 |
55 | ## Monitoring
56 |
57 | The addon assumes that Grafana is installed in a cluster and is available at `${env.url}/grafana`.
58 | Several dashboards are imported to track Java pods memory utilization.
59 |
60 | Once installed, the addon will print URL and names of dashboards to check out.
61 |
--------------------------------------------------------------------------------
/kubernetes/dashboards/java-dashboard-cpu.json:
--------------------------------------------------------------------------------
1 | {
2 | "dashboard": {
3 | "annotations": {
4 | "list": [
5 | {
6 | "builtIn": 1,
7 | "datasource": "-- Grafana --",
8 | "enable": true,
9 | "hide": true,
10 | "iconColor": "rgba(0, 211, 255, 1)",
11 | "name": "Annotations & Alerts",
12 | "type": "dashboard"
13 | }
14 | ]
15 | },
16 | "editable": true,
17 | "gnetId": null,
18 | "graphTooltip": 0,
19 | "links": [],
20 | "panels": [
21 | {
22 | "aliasColors": {},
23 | "bars": false,
24 | "dashLength": 10,
25 | "dashes": false,
26 | "fill": 1,
27 | "fillGradient": 0,
28 | "gridPos": {
29 | "h": 21,
30 | "w": 17,
31 | "x": 6,
32 | "y": 0
33 | },
34 | "id": 2,
35 | "legend": {
36 | "avg": false,
37 | "current": false,
38 | "max": false,
39 | "min": false,
40 | "show": true,
41 | "total": false,
42 | "values": false
43 | },
44 | "lines": true,
45 | "linewidth": 1,
46 | "nullPointMode": "null",
47 | "options": {
48 | "dataLinks": []
49 | },
50 | "percentage": false,
51 | "pointradius": 2,
52 | "points": false,
53 | "renderer": "flot",
54 | "seriesOverrides": [],
55 | "spaceLength": 10,
56 | "stack": false,
57 | "steppedLine": false,
58 | "targets": [
59 | {
60 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"%CONTAINER1%\"}[5m])",
61 | "legendFormat": "%CONTAINER1%",
62 | "refId": "A"
63 | },
64 | {
65 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"%CONTAINER2%\"}[5m])",
66 | "legendFormat": "%CONTAINER2%",
67 | "refId": "B"
68 | },
69 | {
70 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"%CONTAINER3%\"}[5m])",
71 | "legendFormat": "%CONTAINER3%",
72 | "refId": "C"
73 | },
74 | {
75 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"%CONTAINER4%\"}[5m])",
76 | "legendFormat": "%CONTAINER4%",
77 | "refId": "D"
78 | }
79 | ],
80 | "thresholds": [],
81 | "timeFrom": null,
82 | "timeRegions": [],
83 | "timeShift": null,
84 | "title": "Panel Title",
85 | "tooltip": {
86 | "shared": true,
87 | "sort": 0,
88 | "value_type": "individual"
89 | },
90 | "type": "graph",
91 | "xaxis": {
92 | "buckets": null,
93 | "mode": "time",
94 | "name": null,
95 | "show": true,
96 | "values": []
97 | },
98 | "yaxes": [
99 | {
100 | "format": "short",
101 | "label": null,
102 | "logBase": 1,
103 | "max": null,
104 | "min": null,
105 | "show": true
106 | },
107 | {
108 | "format": "short",
109 | "label": null,
110 | "logBase": 1,
111 | "max": null,
112 | "min": null,
113 | "show": true
114 | }
115 | ],
116 | "yaxis": {
117 | "align": false,
118 | "alignLevel": null
119 | }
120 | }
121 | ],
122 | "schemaVersion": 19,
123 | "style": "dark",
124 | "tags": [],
125 | "templating": {
126 | "list": []
127 | },
128 | "time": {
129 | "from": "now-5m",
130 | "to": "now"
131 | },
132 | "timepicker": {
133 | "refresh_intervals": [
134 | "5s",
135 | "10s",
136 | "30s",
137 | "1m",
138 | "5m",
139 | "15m",
140 | "30m",
141 | "1h",
142 | "2h",
143 | "1d"
144 | ]
145 | },
146 | "timezone": "",
147 | "title": "Java CPU %NAME%",
148 | "uid": "java-cpu-%NAME%",
149 | "version": 2
150 | },
151 | "folderId": 0,
152 | "overwrite": false
153 | }
154 |
--------------------------------------------------------------------------------
/kubernetes/dashboards/java-dashboard-mem.json:
--------------------------------------------------------------------------------
1 | {
2 | "dashboard": {
3 | "annotations": {
4 | "list": [
5 | {
6 | "builtIn": 1,
7 | "datasource": "-- Grafana --",
8 | "enable": true,
9 | "hide": true,
10 | "iconColor": "rgba(0, 211, 255, 1)",
11 | "name": "Annotations & Alerts",
12 | "type": "dashboard"
13 | }
14 | ]
15 | },
16 | "editable": true,
17 | "gnetId": null,
18 | "graphTooltip": 0,
19 | "links": [],
20 | "panels": [
21 | {
22 | "aliasColors": {},
23 | "bars": false,
24 | "dashLength": 10,
25 | "dashes": false,
26 | "fill": 1,
27 | "fillGradient": 0,
28 | "gridPos": {
29 | "h": 21,
30 | "w": 17,
31 | "x": 6,
32 | "y": 0
33 | },
34 | "id": 2,
35 | "legend": {
36 | "avg": false,
37 | "current": false,
38 | "max": false,
39 | "min": false,
40 | "show": true,
41 | "total": false,
42 | "values": false
43 | },
44 | "lines": true,
45 | "linewidth": 1,
46 | "nullPointMode": "null",
47 | "options": {
48 | "dataLinks": []
49 | },
50 | "percentage": false,
51 | "pointradius": 2,
52 | "points": false,
53 | "renderer": "flot",
54 | "seriesOverrides": [],
55 | "spaceLength": 10,
56 | "stack": false,
57 | "steppedLine": false,
58 | "targets": [
59 | {
60 | "expr": "sum(container_memory_usage_bytes{container_name=\"%CONTAINER1%\"})/1024/1024/1024",
61 | "legendFormat": "%CONTAINER1%",
62 | "refId": "A"
63 | },
64 | {
65 | "expr": "sum(container_memory_usage_bytes{container_name=\"%CONTAINER2%\"})/1024/1024/1024",
66 | "legendFormat": "%CONTAINER2%",
67 | "refId": "B"
68 | },
69 | {
70 | "expr": "sum(container_memory_usage_bytes{container_name=\"%CONTAINER3%\"})/1024/1024/1024",
71 | "legendFormat": "%CONTAINER3%",
72 | "refId": "C"
73 | },
74 | {
75 | "expr": "sum(container_memory_usage_bytes{container_name=\"%CONTAINER4%\"})/1024/1024/1024",
76 | "legendFormat": "%CONTAINER4%",
77 | "refId": "D"
78 | }
79 | ],
80 | "thresholds": [],
81 | "timeFrom": null,
82 | "timeRegions": [],
83 | "timeShift": null,
84 | "title": "Panel Title",
85 | "tooltip": {
86 | "shared": true,
87 | "sort": 0,
88 | "value_type": "individual"
89 | },
90 | "type": "graph",
91 | "xaxis": {
92 | "buckets": null,
93 | "mode": "time",
94 | "name": null,
95 | "show": true,
96 | "values": []
97 | },
98 | "yaxes": [
99 | {
100 | "format": "short",
101 | "label": null,
102 | "logBase": 1,
103 | "max": null,
104 | "min": null,
105 | "show": true
106 | },
107 | {
108 | "format": "short",
109 | "label": null,
110 | "logBase": 1,
111 | "max": null,
112 | "min": null,
113 | "show": true
114 | }
115 | ],
116 | "yaxis": {
117 | "align": false,
118 | "alignLevel": null
119 | }
120 | }
121 | ],
122 | "schemaVersion": 19,
123 | "style": "dark",
124 | "tags": [],
125 | "templating": {
126 | "list": []
127 | },
128 | "time": {
129 | "from": "now-15m",
130 | "to": "now"
131 | },
132 | "timepicker": {
133 | "refresh_intervals": [
134 | "5s",
135 | "10s",
136 | "30s",
137 | "1m",
138 | "5m",
139 | "15m",
140 | "30m",
141 | "1h",
142 | "2h",
143 | "1d"
144 | ]
145 | },
146 | "timezone": "",
147 | "title": "Java Memory %NAME%",
148 | "uid": "java-mem-%NAME%",
149 | "version": 2
150 | },
151 | "folderId": 0,
152 | "overwrite": false
153 | }
154 |
--------------------------------------------------------------------------------
/kubernetes/deployments/adoptopenjdk.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: java-shenandoah
6 | app: java
7 | name: java-shenandoah
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: java-shenandoah
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: java-shenandoah
19 | app: java
20 | spec:
21 | containers:
22 | - name: java-shenandoah
23 | resources:
24 | limits:
25 | memory: %MEM_LIMIT%
26 | image: jelastic/javaengine:adoptopenjdk-12.0.2
27 | imagePullPolicy: Always
28 | env:
29 | - name: _JAVA_OPTIONS
30 | value: %JAVA_OPTS%
31 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
32 | nodeSelector:
33 | gc: Shenandoah
34 |
--------------------------------------------------------------------------------
/kubernetes/deployments/deployment.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: %NAME%
6 | app: java
7 | name: %NAME%
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: %NAME%
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: %NAME%
19 | app: java
20 | spec:
21 | volumes:
22 | - name: zingmm0
23 | hostPath:
24 | path: /dev/zing_mm0
25 | containers:
26 | - name: %NAME%
27 | resources:
28 | limits:
29 | memory: %MEM_LIMIT%
30 | image: %IMAGE%
31 | imagePullPolicy: Always
32 | securityContext:
33 | privileged: true
34 | capabilities:
35 | add: ["NET_ADMIN", "SYS_TIME", "SYS_RAWIO", "SYS_ADMIN", "ALL"]
36 | env:
37 | - name: _JAVA_OPTIONS
38 | value: %JAVA_OPTS%
39 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
40 | nodeSelector:
41 | opts: %NODE%
42 |
--------------------------------------------------------------------------------
/kubernetes/deployments/dragonwell.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: java-g1-dragonwell
6 | app: java
7 | name: java-g1-dragonwell
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: java-g1-dragonwell
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: java-g1-dragonwell
19 | app: java
20 | spec:
21 | containers:
22 | - name: java-g1-dragonwell
23 | image: devbeta/javaengine:dragonwell-8.1.1
24 | imagePullPolicy: Always
25 | resources:
26 | limits:
27 | memory: %MEM_LIMIT%
28 | env:
29 | - name: _JAVA_OPTIONS
30 | value: %JAVA_OPTS%
31 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
32 | nodeSelector:
33 | gc: G1-dragon
34 |
--------------------------------------------------------------------------------
/kubernetes/deployments/libericajdk12.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: java-g1
6 | app: java
7 | name: java-g1
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: java-g1
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: java-g1
19 | app: java
20 | spec:
21 | containers:
22 | - name: java-g1
23 | resources:
24 | limits:
25 | memory: %MEM_LIMIT%
26 | image: jelastic/javaengine:libericajdk-12.0.2
27 | imagePullPolicy: Always
28 | env:
29 | - name: _JAVA_OPTIONS
30 | value: %JAVA_OPTS%
31 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
32 | nodeSelector:
33 | gc: G1
34 |
--------------------------------------------------------------------------------
/kubernetes/deployments/openj9.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: java-openj9
6 | app: java
7 | name: java-openj9
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: java-openj9
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: java-openj9
19 | app: java
20 | spec:
21 | containers:
22 | - name: java-openj9
23 | resources:
24 | limits:
25 | memory: %MEM_LIMIT%
26 | image: jelastic/javaengine:openj9-0.15.1-12.0.2
27 | imagePullPolicy: Always
28 | env:
29 | - name: OPENJ9_JAVA_OPTIONS
30 | value: %JAVA_OPTS%
31 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
32 | nodeSelector:
33 | gc: OpenJ9
34 |
--------------------------------------------------------------------------------
/kubernetes/deployments/openjdk13.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: java-zgc
6 | app: java
7 | name: java-zgc
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: java-zgc
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: java-zgc
19 | app: java
20 | spec:
21 | containers:
22 | - name: java-zgc
23 | resources:
24 | limits:
25 | memory: %MEM_LIMIT%
26 | image: jelastic/javaengine:openjdk-13.ea-b31
27 | imagePullPolicy: Always
28 | env:
29 | - name: _JAVA_OPTIONS
30 | value: %JAVA_OPTS%
31 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
32 | nodeSelector:
33 | gc: ZGC
34 |
--------------------------------------------------------------------------------
/kubernetes/deployments/zing.yaml:
--------------------------------------------------------------------------------
1 | kind: Deployment
2 | apiVersion: apps/v1
3 | metadata:
4 | labels:
5 | k8s-app: java-c4
6 | app: java
7 | name: java-c4
8 | namespace: java
9 | spec:
10 | replicas: 1
11 | revisionHistoryLimit: 10
12 | selector:
13 | matchLabels:
14 | k8s-app: java-c4
15 | template:
16 | metadata:
17 | labels:
18 | k8s-app: java-c4
19 | app: java
20 | spec:
21 | volumes:
22 | - name: zingmm0
23 | hostPath:
24 | path: /dev/zing_mm0
25 | containers:
26 | - name: java-c4
27 | image: devbeta/javaengine:zing-11.0.0
28 | imagePullPolicy: Always
29 | securityContext:
30 | privileged: true
31 | capabilities:
32 | add: ["NET_ADMIN", "SYS_TIME", "SYS_RAWIO", "SYS_ADMIN", "ALL"]
33 | resources:
34 | limits:
35 | memory: %MEM_LIMIT%
36 | env:
37 | - name: _JAVA_OPTIONS
38 | value: %JAVA_OPTS%
39 | command: ["/bin/bash", "-c", "curl -L https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar --output app.jar && sleep 3 && %CMD%"]
40 | nodeSelector:
41 | gc: C4
42 |
--------------------------------------------------------------------------------
/kubernetes/images/kube.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/6cfdd3c9f4561c00f7b1bd8f03228d3be64145c6/kubernetes/images/kube.png
--------------------------------------------------------------------------------
/kubernetes/java-dashboard-cpu.json:
--------------------------------------------------------------------------------
1 | {
2 | "dashboard": {
3 | "annotations": {
4 | "list": [
5 | {
6 | "builtIn": 1,
7 | "datasource": "-- Grafana --",
8 | "enable": true,
9 | "hide": true,
10 | "iconColor": "rgba(0, 211, 255, 1)",
11 | "name": "Annotations & Alerts",
12 | "type": "dashboard"
13 | }
14 | ]
15 | },
16 | "editable": true,
17 | "gnetId": null,
18 | "graphTooltip": 0,
19 | "links": [],
20 | "panels": [
21 | {
22 | "aliasColors": {},
23 | "bars": false,
24 | "dashLength": 10,
25 | "dashes": false,
26 | "fill": 1,
27 | "fillGradient": 0,
28 | "gridPos": {
29 | "h": 21,
30 | "w": 17,
31 | "x": 6,
32 | "y": 0
33 | },
34 | "id": 2,
35 | "legend": {
36 | "avg": false,
37 | "current": false,
38 | "max": false,
39 | "min": false,
40 | "show": true,
41 | "total": false,
42 | "values": false
43 | },
44 | "lines": true,
45 | "linewidth": 1,
46 | "nullPointMode": "null",
47 | "options": {
48 | "dataLinks": []
49 | },
50 | "percentage": false,
51 | "pointradius": 2,
52 | "points": false,
53 | "renderer": "flot",
54 | "seriesOverrides": [],
55 | "spaceLength": 10,
56 | "stack": false,
57 | "steppedLine": false,
58 | "targets": [
59 | {
60 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"java-c4\"}[5m])",
61 | "legendFormat": "C4",
62 | "refId": "A"
63 | },
64 | {
65 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"java-zgc\"}[5m])",
66 | "legendFormat": "ZGC",
67 | "refId": "B"
68 | },
69 | {
70 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"java-openj9\"}[5m])",
71 | "legendFormat": "OpenJ9",
72 | "refId": "C"
73 | },
74 | {
75 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"java-g1\"}[5m])",
76 | "legendFormat": "G1",
77 | "refId": "D"
78 | },
79 | {
80 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"java-shenandoah\"}[5m])",
81 | "legendFormat": "Shenandoah",
82 | "refId": "E"
83 | },
84 | {
85 | "expr": "rate(container_cpu_usage_seconds_total{container_name=\"java-g1-dragonwell\"}[5m])",
86 | "legendFormat": "Dragonwell",
87 | "refId": "F"
88 | }
89 | ],
90 | "thresholds": [],
91 | "timeFrom": null,
92 | "timeRegions": [],
93 | "timeShift": null,
94 | "title": "Panel Title",
95 | "tooltip": {
96 | "shared": true,
97 | "sort": 0,
98 | "value_type": "individual"
99 | },
100 | "type": "graph",
101 | "xaxis": {
102 | "buckets": null,
103 | "mode": "time",
104 | "name": null,
105 | "show": true,
106 | "values": []
107 | },
108 | "yaxes": [
109 | {
110 | "format": "short",
111 | "label": null,
112 | "logBase": 1,
113 | "max": null,
114 | "min": null,
115 | "show": true
116 | },
117 | {
118 | "format": "short",
119 | "label": null,
120 | "logBase": 1,
121 | "max": null,
122 | "min": null,
123 | "show": true
124 | }
125 | ],
126 | "yaxis": {
127 | "align": false,
128 | "alignLevel": null
129 | }
130 | }
131 | ],
132 | "schemaVersion": 19,
133 | "style": "dark",
134 | "tags": [],
135 | "templating": {
136 | "list": []
137 | },
138 | "time": {
139 | "from": "now-5m",
140 | "to": "now"
141 | },
142 | "timepicker": {
143 | "refresh_intervals": [
144 | "5s",
145 | "10s",
146 | "30s",
147 | "1m",
148 | "5m",
149 | "15m",
150 | "30m",
151 | "1h",
152 | "2h",
153 | "1d"
154 | ]
155 | },
156 | "timezone": "",
157 | "title": "Java CPU",
158 | "uid": "java-cpu",
159 | "version": 2
160 | },
161 | "folderId": 0,
162 | "overwrite": false
163 | }
164 |
--------------------------------------------------------------------------------
/kubernetes/java-dashboard-mem.json:
--------------------------------------------------------------------------------
1 | {
2 | "dashboard": {
3 | "annotations": {
4 | "list": [
5 | {
6 | "builtIn": 1,
7 | "datasource": "-- Grafana --",
8 | "enable": true,
9 | "hide": true,
10 | "iconColor": "rgba(0, 211, 255, 1)",
11 | "name": "Annotations & Alerts",
12 | "type": "dashboard"
13 | }
14 | ]
15 | },
16 | "editable": true,
17 | "gnetId": null,
18 | "graphTooltip": 0,
19 | "links": [],
20 | "panels": [
21 | {
22 | "aliasColors": {},
23 | "bars": false,
24 | "dashLength": 10,
25 | "dashes": false,
26 | "fill": 1,
27 | "fillGradient": 0,
28 | "gridPos": {
29 | "h": 21,
30 | "w": 17,
31 | "x": 6,
32 | "y": 0
33 | },
34 | "id": 2,
35 | "legend": {
36 | "avg": false,
37 | "current": false,
38 | "max": false,
39 | "min": false,
40 | "show": true,
41 | "total": false,
42 | "values": false
43 | },
44 | "lines": true,
45 | "linewidth": 1,
46 | "nullPointMode": "null",
47 | "options": {
48 | "dataLinks": []
49 | },
50 | "percentage": false,
51 | "pointradius": 2,
52 | "points": false,
53 | "renderer": "flot",
54 | "seriesOverrides": [],
55 | "spaceLength": 10,
56 | "stack": false,
57 | "steppedLine": false,
58 | "targets": [
59 | {
60 | "expr": "sum(container_memory_usage_bytes{container_name=\"java-c4\"})/1024/1024/1024",
61 | "legendFormat": "C4",
62 | "refId": "A"
63 | },
64 | {
65 | "expr": "sum(container_memory_usage_bytes{container_name=\"java-zgc\"})/1024/1024/1024",
66 | "legendFormat": "ZGC",
67 | "refId": "B"
68 | },
69 | {
70 | "expr": "sum(container_memory_usage_bytes{container_name=\"java-openj9\"})/1024/1024/1024",
71 | "legendFormat": "OpenJ9",
72 | "refId": "C"
73 | },
74 | {
75 | "expr": "sum(container_memory_usage_bytes{container_name=\"java-g1\"})/1024/1024/1024",
76 | "legendFormat": "G1",
77 | "refId": "D"
78 | },
79 | {
80 | "expr": "sum(container_memory_usage_bytes{container_name=\"java-shenandoah\"})/1024/1024/1024",
81 | "legendFormat": "Shenandoah",
82 | "refId": "E"
83 | },
84 | {
85 | "expr": "sum(container_memory_usage_bytes{container_name=\"java-g1-dragonwell\"})/1024/1024/1024",
86 | "legendFormat": "Dragonwell",
87 | "refId": "F"
88 | }
89 | ],
90 | "thresholds": [],
91 | "timeFrom": null,
92 | "timeRegions": [],
93 | "timeShift": null,
94 | "title": "Panel Title",
95 | "tooltip": {
96 | "shared": true,
97 | "sort": 0,
98 | "value_type": "individual"
99 | },
100 | "type": "graph",
101 | "xaxis": {
102 | "buckets": null,
103 | "mode": "time",
104 | "name": null,
105 | "show": true,
106 | "values": []
107 | },
108 | "yaxes": [
109 | {
110 | "format": "short",
111 | "label": null,
112 | "logBase": 1,
113 | "max": null,
114 | "min": null,
115 | "show": true
116 | },
117 | {
118 | "format": "short",
119 | "label": null,
120 | "logBase": 1,
121 | "max": null,
122 | "min": null,
123 | "show": true
124 | }
125 | ],
126 | "yaxis": {
127 | "align": false,
128 | "alignLevel": null
129 | }
130 | }
131 | ],
132 | "schemaVersion": 19,
133 | "style": "dark",
134 | "tags": [],
135 | "templating": {
136 | "list": []
137 | },
138 | "time": {
139 | "from": "now-15m",
140 | "to": "now"
141 | },
142 | "timepicker": {
143 | "refresh_intervals": [
144 | "5s",
145 | "10s",
146 | "30s",
147 | "1m",
148 | "5m",
149 | "15m",
150 | "30m",
151 | "1h",
152 | "2h",
153 | "1d"
154 | ]
155 | },
156 | "timezone": "",
157 | "title": "Java Memory",
158 | "uid": "java-mem",
159 | "version": 2
160 | },
161 | "folderId": 0,
162 | "overwrite": false
163 | }
164 |
--------------------------------------------------------------------------------
/kubernetes/manifests/actions.jps:
--------------------------------------------------------------------------------
1 | type: update
2 | name: Label Nodes and Create Deployments
3 | onInstall:
4 | - labelNodes
5 | - renameNodes
6 | - setCloudlets
7 | - deploy
8 | - monit
9 | actions:
10 | labelNodes:
11 | - cmd [${nodes.k8sm.master.id}]: curl ${baseUrl}/scripts/label-nodes.sh | bash -s -- opts=${globals.container1} opts=${globals.container2} opts=${globals.container3} opts=${globals.container4}
12 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=opts=${globals.container1} --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
13 | - setGlobals:
14 | node1: ${response.out}
15 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=opts=${globals.container2} --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
16 | - setGlobals:
17 | node2: ${response.out}
18 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=opts=${globals.container3} --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
19 | - setGlobals:
20 | node3: ${response.out}
21 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=opts=${globals.container4} --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
22 | - setGlobals:
23 | node4: ${response.out}
24 | renameNodes:
25 | - jelastic.environment.control.SetNodeDisplayName:
26 | envName: ${env.name}
27 | nodeId: ${globals.node1}
28 | displayName: ${globals.container1}
29 | - jelastic.environment.control.SetNodeDisplayName:
30 | envName: ${env.name}
31 | nodeId: ${globals.node2}
32 | displayName: ${globals.container2}
33 | - jelastic.environment.control.SetNodeDisplayName:
34 | envName: ${env.name}
35 | nodeId: ${globals.node3}
36 | displayName: ${globals.container3}
37 | - jelastic.environment.control.SetNodeDisplayName:
38 | envName: ${env.name}
39 | nodeId: ${globals.node4}
40 | displayName: ${globals.container4}
41 |
42 | setCloudlets:
43 | env.control.SetCloudletsCountByGroup:
44 | nodeGroup: cp
45 | fixedCloudlets: 1
46 | flexibleCloudlets: ${globals.cloudlets}
47 |
48 | deploy:
49 | - cmd [${nodes.k8sm.master.id}]: |-
50 | kubectl create namespace java || true
51 | kubectl delete deployment --force --grace-period=0 -l=app=java -n java || true
52 | kubectl delete pods -n java $(kubectl get pods -l=app=java -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}') --force --grace-period=0 || true
53 | wget ${baseUrl}/dashboards/java-dashboard-mem.json -O java-dashboard-mem.json
54 | wget ${baseUrl}/dashboards/java-dashboard-cpu.json -O java-dashboard-cpu.json
55 |
56 | cat java-dashboard-mem.json | sed "s/%CONTAINER1%/${globals.container1}/g" | sed "s/%CONTAINER2%/${globals.container2}/g" | sed "s/%CONTAINER3%/${globals.container3}/g" | sed "s/%CONTAINER4%/${globals.container4}/g" | sed "s/%NAME%/${globals.name}/g" > java-dashboard-memory.json
57 |
58 | cat java-dashboard-cpu.json | sed "s/%CONTAINER1%/${globals.container1}/g" | sed "s/%CONTAINER2%/${globals.container2}/g" | sed "s/%CONTAINER3%/${globals.container3}/g" | sed "s/%CONTAINER4%/${globals.container4}/g" | sed "s/%NAME%/${globals.name}/g" > java-dashboard-cpu1.json
59 |
60 | export grafana_secret=$(kubectl get secret --namespace kubernetes-monitoring monitoring-grafana -o jsonpath='{.data.admin-password}' | base64 --decode ; echo)
61 | curl -s -k -u "admin:${grafana_secret}" -X POST -H "Accept: application/json" -H "Content-Type: application/json" -d @java-dashboard-memory.json http://${env.domain}/grafana/api/dashboards/db/
62 | curl -s -k -u "admin:${grafana_secret}" -X POST -H "Accept: application/json" -H "Content-Type: application/json" -d @java-dashboard-cpu1.json http://${env.domain}/grafana/api/dashboards/db/
63 | rm java-dashboard-cpu.json java-dashboard-mem.json || true
64 | yaml=${baseUrl}/deployments/deployment.yaml?_r=${fn.random}
65 | curl $yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.opts-container1}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | sed "s/%NAME%/${globals.container1}/g" | sed "s/%NODE%/${globals.container1}/g" | sed "s@%IMAGE%@${globals.image}@g" | kubectl apply -f -
66 | curl $yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.opts-container2}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | sed "s/%NAME%/${globals.container2}/g" | sed "s/%NODE%/${globals.container2}/g" | sed "s@%IMAGE%@${globals.image}@g" | kubectl apply -f -
67 | curl $yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.opts-container3}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | sed "s/%NAME%/${globals.container3}/g" | sed "s/%NODE%/${globals.container3}/g" |sed "s@%IMAGE%@${globals.image}@g" | kubectl apply -f -
68 | curl $yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.opts-container4}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | sed "s/%NAME%/${globals.container4}/g" | sed "s/%NODE%/${globals.container4}/g" | sed "s@%IMAGE%@${globals.image}@g" | kubectl apply -f -
69 |
70 |
71 | monit:
72 | - cmd[${nodes.k8sm.master.id}]: kubectl get secret --namespace kubernetes-monitoring monitoring-grafana -o jsonpath='{.data.admin-password}' | base64 --decode
73 | - setGlobals:
74 | monit_token: ${response.out}
75 | - setGlobals:
76 | success: |
77 | Pods have been deployed to namespace java.
78 |
79 | Get pods: `kubectl get pods -n java`
80 |
81 | Get deployments: `kubectl get deployments -n java`
82 |
83 | Get logs: `kubectl logs -f $deploymentName -n java`
84 |
85 | [Memory Utilization Dashboard](${env.url}grafana/d/java-mem-${globals.name}/java-memory-${globals.name}?orgId=1&refresh=5s&from=now-5m&to=now)
86 |
87 | [CPU Utilization Dashboard](${env.url}grafana/d/java-cpu-${globals.name}/java-cpu-${globals.name}?orgId=1&refresh=5s&from=now-5m&to=now)
88 |
89 | Login: admin : ${globals.monit_token}
90 |
91 | success: ${globals.success}
92 |
--------------------------------------------------------------------------------
/kubernetes/manifests/manifest-k8s-dragonwell-g1.yaml:
--------------------------------------------------------------------------------
1 | type: update
2 | description: |
3 | Java vertical scaling test on Kubernetes: G1 @ Dragonwell 8.1.1
4 |
5 | **Important!** Apply this Add-On to a Kubernetes Cluster with **4** worker nodes.
6 | Each pod is deployed to its dedicated labeled node to easily track memory utilization.
7 |
8 |
9 | name: Java Vertical Scaling on Kubernetes
10 | logo: https://github.com/jelastic/java-vertical-scaling-test/raw/master/kubernetes/images/kube.png
11 | baseUrl: https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/master/kubernetes
12 |
13 | globals:
14 | # keep \\\\n for sed replacement!!!
15 | name: dragonwell
16 | image: devbeta/javaengine:dragonwell-8.1.1
17 | cmd: java --uninstall; echo -ne '\\\\n' | java -jar app.jar 100 2
18 | limit: 3Gi
19 | cloudlets: 40
20 | common: -Xmx3g -Xms3g -XX:+UseCompressedOops -XX:+UseG1GC
21 | container1: custom1
22 | container2: custom2
23 | container3: custom3
24 | container4: default
25 | opts-container1: -XX:+G1ElasticHeap -XX:+ElasticHeapPeriodicUncommit -XX:ElasticHeapPeriodicYGCIntervalMillis=10000 -XX:ElasticHeapYGCIntervalMinMillis=1000 -XX:ElasticHeapInitialMarkIntervalMinMillis=1000 -XX:ElasticHeapPeriodicInitialMarkIntervalMillis=600000 -XX:ElasticHeapPeriodicUncommitStartupDelay=1 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapPeriodicUncommitStartupDelay=10 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapMinYoungCommitPercent=5
26 | opts-container2: -XX:+G1ElasticHeap -XX:+ElasticHeapPeriodicUncommit -XX:ElasticHeapPeriodicYGCIntervalMillis=30000 -XX:ElasticHeapYGCIntervalMinMillis=1000 -XX:ElasticHeapInitialMarkIntervalMinMillis=1000 -XX:ElasticHeapPeriodicInitialMarkIntervalMillis=300000 -XX:ElasticHeapPeriodicUncommitStartupDelay=1 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapPeriodicUncommitStartupDelay=10 -XX:ElasticHeapPeriodicMinYoungCommitPercent=30 -XX:ElasticHeapMinYoungCommitPercent=10
27 | opts-container3: -XX:+G1ElasticHeap -XX:+ElasticHeapPeriodicUncommit -XX:ElasticHeapPeriodicYGCIntervalMillis=10000 -XX:ElasticHeapYGCIntervalMinMillis=1000 -XX:ElasticHeapInitialMarkIntervalMinMillis=1000 -XX:ElasticHeapPeriodicInitialMarkIntervalMillis=60000 -XX:ElasticHeapPeriodicUncommitStartupDelay=1 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapPeriodicUncommitStartupDelay=10 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapMinYoungCommitPercent=5
28 | opts-container4: -XX:+G1ElasticHeap -XX:+ElasticHeapPeriodicUncommit
29 |
30 | mixins:
31 | - manifests/actions.jps
32 |
33 | onInstall:
34 | - labelNodes
35 | - renameNodes
36 | - setCloudlets
37 | - deploy
38 | - monit
39 | success: ${globals.success}
40 |
--------------------------------------------------------------------------------
/kubernetes/manifests/manifest-k8s-openj9.yaml:
--------------------------------------------------------------------------------
1 | type: update
2 | description: |
3 | Java vertical scaling test on Kubernetes: OpenJ9
4 |
5 | **Important!** Apply this Add-On to a Kubernetes Cluster with **4** worker nodes.
6 | Each pod is deployed to its dedicated labeled node to easily track memory utilization.
7 |
8 |
9 | name: Java Vertical Scaling on Kubernetes
10 | logo: https://github.com/jelastic/java-vertical-scaling-test/raw/master/kubernetes/images/kube.png
11 | baseUrl: https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/master/kubernetes
12 |
13 | globals:
14 | # keep \\\\n for sed replacement!!!
15 | name: openj9
16 | image: jelastic/javaengine:openj9-0.15.1-12.0.2
17 | cmd: java --uninstall; echo -ne '\\\\n' | java -jar app.jar 100 2
18 | limit: 3Gi
19 | cloudlets: 40
20 | common: -Xmx3g -Xms32m -XX:+UseCompressedOops
21 | container1: option1
22 | container2: option2
23 | container3: option3
24 | container4: option4
25 |
26 |
27 | opts-container1: -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=1 -Xjit:waitTimeToEnterDeepIdleMode=1000
28 | opts-container2: -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=10 -Xjit:waitTimeToEnterDeepIdleMode=1000
29 | opts-container3: -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=10 -Xjit:waitTimeToEnterDeepIdleMode=10000
30 | opts-container4: -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=10 -Xjit:waitTimeToEnterDeepIdleMode=10000 -Xgc:noConcurrentMark
31 |
32 | mixins:
33 | - manifests/actions.jps
34 |
35 | onInstall:
36 | - labelNodes
37 | - renameNodes
38 | - setCloudlets
39 | - deploy
40 | - monit
41 | success: ${globals.success}
42 |
--------------------------------------------------------------------------------
/kubernetes/manifests/manifest-k8s-zgc.yaml:
--------------------------------------------------------------------------------
1 | type: update
2 | description: |
3 | Java vertical scaling test on Kubernetes: ZGC @ Oracle OpenJDK
4 |
5 | **Important!** Apply this Add-On to a Kubernetes Cluster with **4** worker nodes.
6 | Each pod is deployed to its dedicated labeled node to easily track memory utilization.
7 |
8 |
9 | name: Java Vertical Scaling on Kubernetes
10 | logo: https://github.com/jelastic/java-vertical-scaling-test/raw/master/kubernetes/images/kube.png
11 | baseUrl: https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/master/kubernetes
12 |
13 | globals:
14 | # keep \\\\n for sed replacement!!!
15 | name: zgc
16 | image: jelastic/javaengine:openjdk-13.ea-b31
17 | cmd: java --uninstall; echo -ne '\\\\n' | java -jar app.jar 100 2
18 | limit: 3Gi
19 | cloudlets: 40
20 | common: -Xmx3g -Xms32m -XX:+UseCompressedOops -XX:+UnlockExperimentalVMOptions -XX:+UseZGC
21 | container1: delay1-int30
22 | container2: delay30-int60
23 | container3: delay60-int30
24 | container4: delay30-int1
25 | opts-container1: -XX:ZUncommitDelay=1 -XX:ZCollectionInterval=30
26 | opts-container2: -XX:ZUncommitDelay=30 -XX:ZCollectionInterval=60
27 | opts-container3: -XX:ZUncommitDelay=60 -XX:ZCollectionInterval=30
28 | opts-container4: -XX:ZUncommitDelay=30 -XX:ZCollectionInterval=1
29 |
30 | mixins:
31 | - manifests/actions.jps
32 |
33 | onInstall:
34 | - labelNodes
35 | - renameNodes
36 | - setCloudlets
37 | - deploy
38 | - monit
39 | success: ${globals.success}
40 |
--------------------------------------------------------------------------------
/kubernetes/manifests/manifest-k8s-zing.yaml:
--------------------------------------------------------------------------------
1 | type: update
2 | description: |
3 | Java vertical scaling test on Kubernetes: C4 @ Zing Azul Systems
4 |
5 | **Important!** Apply this Add-On to a Kubernetes Cluster with **4** worker nodes.
6 | Each pod is deployed to its dedicated labeled node to easily track memory utilization.
7 |
8 |
9 | name: Java Vertical Scaling on Kubernetes
10 | logo: https://github.com/jelastic/java-vertical-scaling-test/raw/master/kubernetes/images/kube.png
11 | baseUrl: https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/master/kubernetes
12 |
13 | globals:
14 | # keep \\\\n for sed replacement!!!
15 | name: zing
16 | image: devbeta/javaengine:zing-11.0.0
17 | cmd: java --uninstall; echo -ne '\\\\n' | java -jar app.jar 100 2
18 | limit: 3Gi
19 | cloudlets: 40
20 | common: -XX:+UseCompressedOops -XX:+UseZST -XX:-AutoTuneResourceDefaultsBasedOnXmx
21 | container1: xmx256m
22 | container2: xmx512m
23 | container3: xmx1024m
24 | container4: xmx2024m
25 | opts-container1: -Xmx256m
26 | opts-container2: -Xmx512m
27 | opts-container3: -Xmx1024m
28 | opts-container4: -Xmx2024m
29 |
30 | mixins:
31 | - manifests/actions.jps?_r=${fn.random}
32 |
33 | onInstall:
34 | - labelNodes
35 | - renameNodes
36 | - setCloudlets
37 | - deploy
38 | - monit
39 | success: ${globals.success}
40 |
--------------------------------------------------------------------------------
/kubernetes/scripts/grafana.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | grafana_host=$1
3 | grafana_secret=$(kubectl get secret --namespace kubernetes-monitoring monitoring-grafana -o jsonpath='{.data.admin-password}' | base64 --decode ; echo)
4 | grafana_cred="admin:${grafana_secret}"
5 | grafana_datasource="Prometheus"
6 | ds=(1471 10000 5228 7249);
7 | echo -n "Processing dashboard: "
8 | for d in "${ds[@]}"; do
9 | echo -n "Processing $d: "
10 | j=$(curl -s -k -u "$grafana_cred" $grafana_host/api/gnet/dashboards/$d | jq .json)
11 | curl -s -k -u "$grafana_cred" -XPOST -H "Accept: application/json" \
12 | -H "Content-Type: application/json" \
13 | -d "{\"dashboard\":$j,\"overwrite\":true, \
14 | \"inputs\":[{\"name\":\"DS_PROMETHEUS\",\"type\":\"datasource\", \
15 | \"pluginId\":\"Jelastic\",\"value\":\"$grafana_datasource\"}]}" \
16 | $grafana_host/api/dashboards/import; echo ""
17 | done
--------------------------------------------------------------------------------
/kubernetes/scripts/label-nodes.sh:
--------------------------------------------------------------------------------
1 | NODES=$(kubectl get nodes | grep \ | awk '{print $1}')
2 | NODES=(${NODES// / })
3 | LABELS=($1 $2 $3 $4)
4 | for i in ${!NODES[*]}; do
5 | kubectl label nodes ${NODES[$i]} ${LABELS[$i]} --overwrite
6 | done
7 |
--------------------------------------------------------------------------------
/kubernetes/scripts/labelnodes.sh:
--------------------------------------------------------------------------------
1 | NODES=$(kubectl get nodes | grep \ | awk '{print $1}')
2 | NODES=(${NODES// / })
3 | LABELS=(gc=ZGC gc=Shenandoah gc=C4 gc=OpenJ9 gc=G1 gc=G1-dragon)
4 | for i in ${!NODES[*]}; do
5 | kubectl label nodes ${NODES[$i]} ${LABELS[$i]} --overwrite
6 | done
7 |
--------------------------------------------------------------------------------
/manifest-k8s.yaml:
--------------------------------------------------------------------------------
1 | type: update
2 | description: |
3 | Java vertical scaling test on Kubernetes:
4 | * G1
5 | * Shenandoah
6 | * G1 @ Dragonwell 8.1.1
7 | * ZGC @ Oracle OpenJDK
8 | * C4 @ Zing
9 | * OpenJ9
10 |
11 | **Important!** Apply this Add-On to a Kubernetes Cluster with **6** worker nodes.
12 | Each pod is deployed to its dedicated labeled node to easily track memory utilization.
13 |
14 |
15 | name: Java Vertical Scaling on Kubernetes
16 | logo: https://github.com/jelastic/java-vertical-scaling-test/raw/master/kubernetes/images/kube.png
17 | baseUrl: https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/master/kubernetes
18 |
19 | globals:
20 | # keep \\\\n for sed replacement!!!
21 | cmd: java --uninstall; echo -ne '\\\\n' | java -jar app.jar 100 2
22 | limit: 3Gi
23 | cloudlets: 40
24 | common: -Xmx3g -Xms32m -XX:+UseCompressedOops
25 | zing: -Xmx500m -Xms32m -XX:+UseCompressedOops -XX:+UseZST
26 | openjdk: -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZUncommitDelay=30 -XX:ZCollectionInterval=60
27 | openj9: -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=10 -Xjit:waitTimeToEnterDeepIdleMode=10000 -Xgc:noConcurrentMark
28 | adoptopenjdk: -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
29 | liberica: -XX:+UseG1GC -XX:G1PeriodicGCInterval=10k
30 | dragonwell: -Xmx3g -Xms3g -XX:+UseCompressedOops -XX:+UseG1GC -XX:+G1ElasticHeap -XX:+ElasticHeapPeriodicUncommit -XX:ElasticHeapPeriodicYGCIntervalMillis=10000 -XX:ElasticHeapYGCIntervalMinMillis=1000 -XX:ElasticHeapInitialMarkIntervalMinMillis=1000 -XX:ElasticHeapPeriodicInitialMarkIntervalMillis=60000 -XX:ElasticHeapPeriodicUncommitStartupDelay=1 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapPeriodicUncommitStartupDelay=10 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10 -XX:ElasticHeapMinYoungCommitPercent=5
31 |
32 | onInstall:
33 | - labelNodes
34 | - renameNodes
35 | - setCloudlets
36 | - deploy
37 | - monit
38 | - getPods
39 | actions:
40 | labelNodes:
41 | - cmd [${nodes.k8sm.master.id}]: curl ${baseUrl}/scripts/labelnodes.sh | bash
42 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=gc=ZGC --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
43 | - setGlobals:
44 | zgcNode: ${response.out}
45 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=gc=Shenandoah --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
46 | - setGlobals:
47 | shenandoahNode: ${response.out}
48 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=gc=OpenJ9 --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
49 | - setGlobals:
50 | openj9Node: ${response.out}
51 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=gc=G1 --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
52 | - setGlobals:
53 | g1Node: ${response.out}
54 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=gc=C4 --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
55 | - setGlobals:
56 | c4Node: ${response.out}
57 | - cmd[${nodes.k8sm.master.id}]: kubectl get node -l=gc=G1-dragon --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}' | awk -F"-" '{print $1}' | cut -c5-
58 | - setGlobals:
59 | dragonNode: ${response.out}
60 | renameNodes:
61 | - jelastic.environment.control.SetNodeDisplayName:
62 | envName: ${env.name}
63 | nodeId: ${globals.zgcNode}
64 | displayName: ZGC
65 | - jelastic.environment.control.SetNodeDisplayName:
66 | envName: ${env.name}
67 | nodeId: ${globals.shenandoahNode}
68 | displayName: Shenandoah
69 | - jelastic.environment.control.SetNodeDisplayName:
70 | envName: ${env.name}
71 | nodeId: ${globals.openj9Node}
72 | displayName: Openj9
73 | - jelastic.environment.control.SetNodeDisplayName:
74 | envName: ${env.name}
75 | nodeId: ${globals.g1Node}
76 | displayName: G1
77 | - jelastic.environment.control.SetNodeDisplayName:
78 | envName: ${env.name}
79 | nodeId: ${globals.c4Node}
80 | displayName: C4
81 | - jelastic.environment.control.SetNodeDisplayName:
82 | envName: ${env.name}
83 | nodeId: ${globals.dragonNode}
84 | displayName: G1-Dragonwell
85 | setCloudlets:
86 | env.control.SetCloudletsCountByGroup:
87 | nodeGroup: cp
88 | fixedCloudlets: 1
89 | flexibleCloudlets: ${globals.cloudlets}
90 |
91 | deploy:
92 | - cmd [${nodes.k8sm.master.id}]: |-
93 | kubectl create namespace java || true
94 | kubectl delete deployment --force --grace-period=0 -l=app=java -n java || true
95 | kubectl delete pods -n java $(kubectl get pods -l=app=java -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}') --force --grace-period=0 || true
96 | wget ${baseUrl}/java-dashboard-mem.json -O java-dashboard-mem.json
97 | wget ${baseUrl}/java-dashboard-cpu.json -O java-dashboard-cpu.json
98 | export grafana_secret=$(kubectl get secret --namespace kubernetes-monitoring monitoring-grafana -o jsonpath='{.data.admin-password}' | base64 --decode ; echo)
99 | curl -s -k -u "admin:${grafana_secret}" -X POST -H "Accept: application/json" -H "Content-Type: application/json" -d @java-dashboard-mem.json http://${env.domain}/grafana/api/dashboards/db/
100 | curl -s -k -u "admin:${grafana_secret}" -X POST -H "Accept: application/json" -H "Content-Type: application/json" -d @java-dashboard-cpu.json http://${env.domain}/grafana/api/dashboards/db/
101 | curl ${baseUrl}/deployments/adoptopenjdk.yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.adoptopenjdk}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
102 | curl ${baseUrl}/deployments/libericajdk12.yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.liberica}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
103 | curl ${baseUrl}/deployments/openj9.yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.openj9}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
104 | curl ${baseUrl}/deployments/openjdk13.yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.openjdk}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
105 | curl ${baseUrl}/deployments/zulujdk.yaml | sed "s/%JAVA_OPTS%/${globals.common} ${globals.zulujdk}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
106 | curl ${baseUrl}/deployments/zing.yaml | sed "s/%JAVA_OPTS%/${globals.zing}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
107 | curl ${baseUrl}/deployments/dragonwell.yaml | sed "s/%JAVA_OPTS%/${globals.dragonwell}/g" | sed "s/%MEM_LIMIT%/${globals.limit}/g" | sed "s/%CMD%/${globals.cmd}/g" | kubectl apply -f -
108 | monit:
109 | - cmd[${nodes.k8sm.master.id}]: kubectl get secret --namespace kubernetes-monitoring monitoring-grafana -o jsonpath='{.data.admin-password}' | base64 --decode
110 | - setGlobals:
111 | monit_token: ${response.out}
112 | getPods:
113 | - cmd[${nodes.k8sm.master.id}]: kubectl get pods -l=k8s-app=java-shenandoah -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}'
114 | - setGlobals:
115 | adoptOpenJDKPod: ${response.out}
116 | - cmd[${nodes.k8sm.master.id}]: kubectl get pods -l=k8s-app=java-g1 -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}'
117 | - setGlobals:
118 | libericajdkPod: ${response.out}
119 | - cmd[${nodes.k8sm.master.id}]: kubectl get pods -l=k8s-app=java-openj9 -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}'
120 | - setGlobals:
121 | openj9Pod: ${response.out}
122 | - cmd[${nodes.k8sm.master.id}]: kubectl get pods -l=k8s-app=java-zgc -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}'
123 | - setGlobals:
124 | openjdkPod: ${response.out}
125 | - cmd[${nodes.k8sm.master.id}]: kubectl get pods -l=k8s-app=java-c4 -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}'
126 | - setGlobals:
127 | zingPod: ${response.out}
128 | - cmd[${nodes.k8sm.master.id}]: kubectl get pods -l=k8s-app=java-g1-dragonwell -n java --template '{{range .items}}{{.metadata.name}}{{"\n"}}{{end}}' | awk '{print $1}'
129 | - setGlobals:
130 | dragonwell: ${response.out}
131 | - setGlobals:
132 | success: |
133 | Pods have been deployed to namespace java.
134 |
135 | Get pods: `kubectl get pods -n java`
136 |
137 | Get deployments: `kubectl get deployments -n java`
138 |
139 | Get logs: `kubectl logs -f $deploymentName -n java`
140 |
141 | [Memory Utilization Dashboard](${env.url}grafana/d/java-mem/java-memory?orgId=1&refresh=5s&from=now-5m&to=now)
142 |
143 | [CPU Utilization Dashboard](${env.url}grafana/d/java-cpu/java-cpu?orgId=1&refresh=5s&from=now-5m&to=now)
144 |
145 | Login: admin : ${globals.monit_token}
146 |
147 | success: ${globals.success}
148 |
--------------------------------------------------------------------------------
/manifest.yml:
--------------------------------------------------------------------------------
1 | type: install
2 | id: java-memory-usage-demo
3 | name: Java Vertical Scaling
4 | baseUrl: https://raw.githubusercontent.com/jelastic/java-vertical-scaling-test/master
5 | homepage: https://github.com/jelastic/java-vertical-scaling-test
6 | logo: /images/elastic-duke-70x70.png
7 | description: |
8 | Java vertical scaling test:
9 | * G1 @ Zulu 12.0.2
10 | * G1 @ Dragonwell 8.1.1
11 | * Shenandoah
12 | * ZGC @ Oracle OpenJDK
13 | * C4 @ Zing
14 | * OpenJ9
15 | * Serial
16 | * CMS
17 | * Epsilon
18 | * Parallel
19 |
20 | globals:
21 | cloudlets: 26
22 | common: -Xmx3g -Xms32m -XX:+UseCompressedOops
23 | nodes:
24 | - nodeType: javaengine
25 | tag: zulujdk-12.0.2
26 | nodeGroup: g1
27 | cloudlets: ${globals.cloudlets}
28 | displayName: G1 @ Zulu 12
29 | startService: false
30 | env:
31 | _JAVA_OPTIONS: ${globals.common} -XX:+UseG1GC -XX:G1PeriodicGCInterval=1k
32 |
33 | - image: devbeta/javaengine:dragonwell-8.1.1
34 | nodeGroup: dw
35 | cloudlets: ${globals.cloudlets}
36 | displayName: G1 @ Dragonwell 8
37 | startService: false
38 | env:
39 | _JAVA_OPTIONS: -Xmx3g -Xms3g -XX:+UseCompressedOops -XX:+UseG1GC -XX:+G1ElasticHeap -XX:+ElasticHeapPeriodicUncommit -XX:ElasticHeapPeriodicYGCIntervalMillis=10000 -XX:ElasticHeapYGCIntervalMinMillis=1000 -XX:ElasticHeapInitialMarkIntervalMinMillis=1000 -XX:ElasticHeapPeriodicInitialMarkIntervalMillis=300000 -XX:ElasticHeapPeriodicUncommitStartupDelay=1 -XX:ElasticHeapPeriodicMinYoungCommitPercent=10
40 |
41 | - nodeType: javaengine
42 | tag: zulujdk-12.0.2
43 | nodeGroup: shenan
44 | cloudlets: ${globals.cloudlets}
45 | displayName: Shenandoah
46 | startService: false
47 | #-XX:ShenandoahGCHeuristics=compact is very agressive mode
48 | env:
49 | _JAVA_OPTIONS: ${globals.common} -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC -XX:ShenandoahGCHeuristics=compact
50 | - nodeType: javaengine
51 | tag: openjdk-13.ea-b31
52 | nodeGroup: zgc
53 | cloudlets: ${globals.cloudlets}
54 | displayName: ZGC @ Oracle OpenJDK
55 | startService: false
56 | #-XX:ZUncommitDelay=1 -XX:ZCollectionInterval=30 is very agressive mode as well, similar to Shenandoah
57 | env:
58 | _JAVA_OPTIONS: ${globals.common} -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZUncommitDelay=30 -XX:ZCollectionInterval=60
59 |
60 | - nodeType: javaengine
61 | tag: zulujdk-12.0.2
62 | nodeGroup: epsilon
63 | cloudlets: ${globals.cloudlets}
64 | displayName: Epsilon
65 | startService: false
66 | env:
67 | _JAVA_OPTIONS: ${globals.common} -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC
68 |
69 | - nodeType: javaengine
70 | tag: openj9-0.15.1-12.0.2
71 | nodeGroup: openj9
72 | cloudlets: ${globals.cloudlets}
73 | displayName: OpenJ9
74 | startService: false
75 | env:
76 | OPENJ9_JAVA_OPTIONS: ${globals.common} -XX:+IdleTuningCompactOnIdle -XX:+IdleTuningGcOnIdle -XX:IdleTuningMinIdleWaitTime=1 -Xjit:waitTimeToEnterDeepIdleMode=1000
77 |
78 | - image: devbeta/javaengine:zing-11.0.0
79 | nodeGroup: zing
80 | cloudlets: ${globals.cloudlets}
81 | displayName: C4 @ Zing
82 | startService: false
83 | env:
84 | _JAVA_OPTIONS: -Xmx500m -XX:+UseCompressedOops -XX:+UseZST
85 |
86 | - nodeType: javaengine
87 | tag: zulujdk-12.0.2
88 | nodeGroup: cms
89 | cloudlets: ${globals.cloudlets}
90 | displayName: ConcMarkSweep
91 | startService: false
92 | env:
93 | _JAVA_OPTIONS: ${globals.common} -XX:+UseConcMarkSweepGC
94 |
95 | - nodeType: javaengine
96 | tag: zulujdk-12.0.2
97 | nodeGroup: parallel
98 | cloudlets: ${globals.cloudlets}
99 | displayName: Parallel
100 | startService: false
101 | env:
102 | _JAVA_OPTIONS: ${globals.common} -XX:+UseParallelGC
103 |
104 | - nodeType: javaengine
105 | tag: zulujdk-12.0.2
106 | nodeGroup: serial
107 | cloudlets: ${globals.cloudlets}
108 | displayName: Serial
109 | startService: false
110 | env:
111 | _JAVA_OPTIONS: ${globals.common} -XX:+UseSerialGC
112 |
113 |
114 | onInstall:
115 | - cmd[*]: |-
116 | chmod 775 /var/run/screen
117 | chmod 777 /var/log/run.log
118 | java --uninstall
119 | user: root
120 | - cmd[*]: |-
121 | wget https://github.com/jelastic/java-vertical-scaling-test/raw/master/dist/app.jar
122 | screen -dm bash -c "echo -ne '\n' | java -jar app.jar 100 2 &>> /var/log/run.log"
123 | - cmd[serial, cms, parallel, epsilon]: |-
124 | screen -dm bash -c 'sleep 300; while true; do a="app"; j=".jar"; /usr/java/latest/bin/jcmd $(pgrep -f $a$j | tail -n1) GC.run &>> /var/log/run.log; sleep 20; done;'
125 |
126 | # OpenJ9 memory usage should be tracked in a tricky way
127 | # while true; do used=$(ps -orss --no-headers --pid $(pgrep -f java | tail -n1)); echo "scale=2 ; $used / 1024*1024" | bc; sleep 1; done
128 |
--------------------------------------------------------------------------------
/src/com/jelastic/verticalscaling/Load.java:
--------------------------------------------------------------------------------
1 | package com.jelastic.verticalscaling;
2 |
3 | import java.io.IOException;
4 | import java.util.LinkedList;
5 | import java.util.List;
6 |
7 | /**
8 | *
9 | * @author ruslan
10 | */
11 | public class Load {
12 |
13 | private int sleep = 0;
14 | private int longSleep = 60000;
15 | private int numCycles = 3;
16 | private int mode = 1;
17 |
18 | public Load(int sleep) {
19 | this.sleep = sleep;
20 | }
21 |
22 | public Load(int sleep, int mode) {
23 | this(sleep);
24 | this.mode = mode;
25 | }
26 |
27 | public void run() throws IOException, InterruptedException {
28 | long start = System.currentTimeMillis();
29 | try {
30 | switch (mode) {
31 | case 1:
32 | simple();
33 | break;
34 | case 2:
35 | gil();
36 | break;
37 | default:
38 | System.out.println("Unknown load mode: " + mode);
39 | }
40 |
41 | } catch (OutOfMemoryError e) {
42 | e.printStackTrace();
43 | }
44 | System.out.println("total time = " + (System.currentTimeMillis() - start) + ", ms");
45 | System.out.println("done");
46 |
47 | }
48 |
49 | private void simple() throws InterruptedException, OutOfMemoryError {
50 | int n = 1 * 1024 * 512 / 2;
51 | List list = new LinkedList();
52 | for (int i = 0; i < n; i++) {
53 | String[] str = new String[1024];
54 | list.add(str);
55 | if (i % 100 == 0) {
56 | //System.out.println("i=" + i);
57 | Thread.sleep(sleep);
58 | }
59 | }
60 | }
61 |
62 | private static volatile Object foo[] = new Object[20];
63 |
64 | private void gil() throws InterruptedException, OutOfMemoryError {
65 | int ratio = 20;
66 | for (int k = 0; k < numCycles; k++) {
67 | int n = 1 * 1024 * 512 / 3 ;
68 | List list = new LinkedList();
69 | for (int i = 0; i < n; i++) {
70 | String[] str = new String[1024];
71 | list.add(str);
72 | for (int r = 0; r < ratio; r++) {
73 | foo[r] = new String[1024];
74 | }
75 | if (i % 100 == 0) {
76 | Thread.sleep(sleep);
77 | }
78 | }
79 | System.out.println("Load is finished. Sleeping...");
80 | Thread.sleep(longSleep);
81 | list.clear();
82 | System.out.println("Calling list.clear(). Sleeping...");
83 | Thread.sleep(longSleep);
84 | System.gc();
85 | System.out.println("Calling System.gc(). Sleeping...");
86 | Thread.sleep(longSleep);
87 | }
88 | }
89 |
90 | }
91 |
--------------------------------------------------------------------------------
/src/com/jelastic/verticalscaling/MemoryUsage.java:
--------------------------------------------------------------------------------
1 | package com.jelastic.verticalscaling;
2 |
3 | import java.lang.management.ManagementFactory;
4 | import java.lang.management.MemoryMXBean;
5 | import java.text.SimpleDateFormat;
6 | import java.util.Date;
7 | import java.util.logging.Level;
8 | import java.util.logging.Logger;
9 |
10 | /**
11 | *
12 | * @author ruslan
13 | */
14 | public class MemoryUsage implements Runnable {
15 |
16 | @Override
17 | public void run() {
18 |
19 | while (true) {
20 | try {
21 | Thread.sleep(3000);
22 | } catch (InterruptedException ex) {
23 | Logger.getLogger(MemoryUsage.class.getName()).log(Level.SEVERE, null, ex);
24 | }
25 | java.lang.management.MemoryUsage mu = ManagementFactory.getMemoryMXBean().getHeapMemoryUsage();
26 |
27 | Date dNow = new Date( );
28 | SimpleDateFormat ft = new SimpleDateFormat ("hh:mm:ss");
29 |
30 | print(ft.format(dNow) + " -> Init", mu.getInit());
31 | print("Used", mu.getUsed());
32 | print("Committed", mu.getCommitted());
33 | print("Max", mu.getMax());
34 |
35 | System.out.println();
36 | }
37 |
38 | }
39 |
40 | private void print(String name, double value) {
41 | System.out.print(name + ": " + Math.round(value / 1024 / 1024) + "M ");
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/com/jelastic/verticalscaling/Test.java:
--------------------------------------------------------------------------------
1 | package com.jelastic.verticalscaling;
2 |
3 | import java.io.IOException;
4 |
5 | /**
6 | *
7 | * @author ruslan
8 | */
9 | public class Test {
10 |
11 | /**
12 | * @param args the command line arguments
13 | */
14 | public static void main(String[] args) throws InterruptedException, IOException {
15 | System.out.println("Press to start the load test");
16 | int sleep = 10;
17 | if (args.length > 0) {
18 | sleep = Integer.parseInt(args[0]);
19 | }
20 | int mode = 1;
21 | if (args.length > 1) {
22 | mode = Integer.parseInt(args[1]);
23 | }
24 | boolean gc = false;
25 | if (args.length > 2) {
26 | gc = Boolean.parseBoolean(args[2]);
27 | }
28 | int nGc = 1;
29 | if (args.length > 3) {
30 | nGc = Integer.parseInt(args[3]);
31 | }
32 | new Thread(new MemoryUsage()).start();
33 | while (true) {
34 | int n = System.in.read();
35 | if (n > -1) {
36 | Load test = new Load(sleep, mode);
37 | test.run();
38 | test = null;
39 | }
40 |
41 | Thread.sleep(10000);
42 | if (gc) {
43 | for (int i = 0; i < nGc; i++) {
44 | System.out.println("Calling GC...");
45 | System.gc();
46 | }
47 | }
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------