@@ -56,7 +56,7 @@ private JvmErgonomics() {
56
56
*/
57
57
static List <String > choose (final List <String > userDefinedJvmOptions ) throws InterruptedException , IOException {
58
58
final List <String > ergonomicChoices = new ArrayList <>();
59
- final Map <String , Optional < String > > finalJvmOptions = finalJvmOptions (userDefinedJvmOptions );
59
+ final Map <String , JvmOption > finalJvmOptions = finalJvmOptions (userDefinedJvmOptions );
60
60
final long heapSize = extractHeapSize (finalJvmOptions );
61
61
final long maxDirectMemorySize = extractMaxDirectMemorySize (finalJvmOptions );
62
62
@@ -75,20 +75,59 @@ static List<String> choose(final List<String> userDefinedJvmOptions) throws Inte
75
75
76
76
ergonomicChoices .add ("-XX:MaxDirectMemorySize=" + heapSize / 2 );
77
77
}
78
+ // Elasticsearch supports G1GC on JDK10+
79
+ if (JavaVersion .majorVersion (JavaVersion .CURRENT ) >= 10 ) {
80
+ final boolean tuneG1GCForSmallHeap = tuneG1GCForSmallHeap (heapSize );
81
+ final boolean tuneG1GCHeapRegion = tuneG1GCHeapRegion (finalJvmOptions , tuneG1GCForSmallHeap );
82
+ final boolean tuneG1GCInitiatingHeapOccupancyPercent = tuneG1GCInitiatingHeapOccupancyPercent (finalJvmOptions );
83
+ final int tuneG1GCReservePercent = tuneG1GCReservePercent (finalJvmOptions , tuneG1GCForSmallHeap );
84
+
85
+ if (tuneG1GCHeapRegion ) {
86
+ ergonomicChoices .add ("-XX:G1HeapRegionSize=4m" );
87
+ }
88
+ if (tuneG1GCInitiatingHeapOccupancyPercent ) {
89
+ ergonomicChoices .add ("-XX:InitiatingHeapOccupancyPercent=30" );
90
+ }
91
+ if (tuneG1GCReservePercent != 0 ) {
92
+ ergonomicChoices .add ("-XX:G1ReservePercent=" + tuneG1GCReservePercent );
93
+ }
94
+ }
95
+
78
96
return ergonomicChoices ;
79
97
}
80
98
81
99
private static final Pattern OPTION = Pattern .compile (
82
- "^\\ s*\\ S+\\ s+(?<flag>\\ S+)\\ s+:?=\\ s+(?<value>\\ S+)?\\ s+\\ {[^}]+?\\ }(\\ s+\\ {[^}]+})?"
100
+ "^\\ s*\\ S+\\ s+(?<flag>\\ S+)\\ s+:?=\\ s+(?<value>\\ S+)?\\ s+\\ {[^}]+?\\ }(\\ s+\\ {(?<origin> [^}]+) })?"
83
101
);
84
102
85
- static Map <String , Optional <String >> finalJvmOptions (final List <String > userDefinedJvmOptions ) throws InterruptedException ,
86
- IOException {
103
+ private static class JvmOption {
104
+ private final String value ;
105
+ private final String origin ;
106
+
107
+ JvmOption (String value , String origin ) {
108
+ this .value = value ;
109
+ this .origin = origin ;
110
+ }
111
+
112
+ public Optional <String > getValue () {
113
+ return Optional .ofNullable (value );
114
+ }
115
+
116
+ public String getMandatoryValue () {
117
+ return value ;
118
+ }
119
+
120
+ public boolean isCommandLineOrigin () {
121
+ return "command line" .equals (this .origin );
122
+ }
123
+ }
124
+
125
+ static Map <String , JvmOption > finalJvmOptions (final List <String > userDefinedJvmOptions ) throws InterruptedException , IOException {
87
126
return Collections .unmodifiableMap (
88
127
flagsFinal (userDefinedJvmOptions ).stream ()
89
128
.map (OPTION ::matcher )
90
129
.filter (Matcher ::matches )
91
- .collect (Collectors .toMap (m -> m .group ("flag" ), m -> Optional . ofNullable (m .group ("value" ))))
130
+ .collect (Collectors .toMap (m -> m .group ("flag" ), m -> new JvmOption (m .group ("value" ), m . group ( "origin " ))))
92
131
);
93
132
}
94
133
@@ -136,12 +175,42 @@ private static List<String> readLinesFromInputStream(final InputStream is) throw
136
175
}
137
176
138
177
// package private for testing
139
- static Long extractHeapSize (final Map <String , Optional <String >> finalJvmOptions ) {
140
- return Long .parseLong (finalJvmOptions .get ("MaxHeapSize" ).get ());
178
+ static Long extractHeapSize (final Map <String , JvmOption > finalJvmOptions ) {
179
+ return Long .parseLong (finalJvmOptions .get ("MaxHeapSize" ).getMandatoryValue ());
180
+ }
181
+
182
+ static long extractMaxDirectMemorySize (final Map <String , JvmOption > finalJvmOptions ) {
183
+ return Long .parseLong (finalJvmOptions .get ("MaxDirectMemorySize" ).getMandatoryValue ());
184
+ }
185
+
186
+ // Tune G1GC options for heaps < 8GB
187
+ static boolean tuneG1GCForSmallHeap (final long heapSize ) {
188
+ return heapSize < 8L << 30 ;
189
+ }
190
+
191
+ static boolean tuneG1GCHeapRegion (final Map <String , JvmOption > finalJvmOptions , final boolean tuneG1GCForSmallHeap ) {
192
+ JvmOption g1GCHeapRegion = finalJvmOptions .get ("G1HeapRegionSize" );
193
+ JvmOption g1GC = finalJvmOptions .get ("UseG1GC" );
194
+ return (tuneG1GCForSmallHeap && g1GC .getMandatoryValue ().equals ("true" ) && g1GCHeapRegion .isCommandLineOrigin () == false );
195
+ }
196
+
197
+ static int tuneG1GCReservePercent (final Map <String , JvmOption > finalJvmOptions , final boolean tuneG1GCForSmallHeap ) {
198
+ JvmOption g1GC = finalJvmOptions .get ("UseG1GC" );
199
+ JvmOption g1GCReservePercent = finalJvmOptions .get ("G1ReservePercent" );
200
+ if (g1GC .getMandatoryValue ().equals ("true" )) {
201
+ if (g1GCReservePercent .isCommandLineOrigin () == false && tuneG1GCForSmallHeap ) {
202
+ return 15 ;
203
+ } else if (g1GCReservePercent .isCommandLineOrigin () == false && tuneG1GCForSmallHeap == false ) {
204
+ return 25 ;
205
+ }
206
+ }
207
+ return 0 ;
141
208
}
142
209
143
- static long extractMaxDirectMemorySize (final Map <String , Optional <String >> finalJvmOptions ) {
144
- return Long .parseLong (finalJvmOptions .get ("MaxDirectMemorySize" ).get ());
210
+ static boolean tuneG1GCInitiatingHeapOccupancyPercent (final Map <String , JvmOption > finalJvmOptions ) {
211
+ JvmOption g1GC = finalJvmOptions .get ("UseG1GC" );
212
+ JvmOption g1GCInitiatingHeapOccupancyPercent = finalJvmOptions .get ("InitiatingHeapOccupancyPercent" );
213
+ return g1GCInitiatingHeapOccupancyPercent .isCommandLineOrigin () == false && g1GC .getMandatoryValue ().equals ("true" );
145
214
}
146
215
147
216
private static final Pattern SYSTEM_PROPERTY = Pattern .compile ("^-D(?<key>[\\ w+].*?)=(?<value>.*)$" );
0 commit comments