Skip to content

Commit e79d157

Browse files
[GR-38414] [GR-44546] MemoryPoolMXBean improvements for serial and epsilon GC.
PullRequest: graal/13873
2 parents c9742d8 + f728359 commit e79d157

File tree

14 files changed

+554
-40
lines changed

14 files changed

+554
-40
lines changed

substratevm/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ This changelog summarizes major changes to GraalVM Native Image.
2222
* (GR-44216) Native Image is now shipped as part of the GraalVM JDK and thus no longer needs to be installed via `gu install native-image`.
2323
* (GR-44105) A warning is displayed when trying to generate debug info on macOS since that is not supported. It is now an error to use `-H:+StripDebugInfo` on macOS or `-H:-StripDebugInfo` on Windows since those values are not supported.
2424
* (GR-43966) Remove analysis options -H:AnalysisStatisticsFile and -H:ImageBuildStatisticsFile. Output files are now written to fixed subdirectories relative to image location (reports/image_build_statistics.json).
25+
* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs.
2526
* (GR-40641) Dynamic linking of AWT libraries on Linux.
2627

2728
## Version 22.3.0

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626

2727
import java.util.concurrent.atomic.AtomicBoolean;
2828

29-
import com.oracle.svm.core.heap.GCCause;
3029
import org.graalvm.compiler.api.replacements.Fold;
3130
import org.graalvm.compiler.nodes.PauseNode;
3231
import org.graalvm.nativeimage.Platform;
@@ -36,6 +35,7 @@
3635

3736
import com.oracle.svm.core.SubstrateGCOptions;
3837
import com.oracle.svm.core.Uninterruptible;
38+
import com.oracle.svm.core.heap.GCCause;
3939
import com.oracle.svm.core.heap.PhysicalMemory;
4040
import com.oracle.svm.core.heap.ReferenceAccess;
4141
import com.oracle.svm.core.jdk.UninterruptibleUtils;
@@ -193,13 +193,21 @@ private void updateSizeParametersLocked(SizeParameters params, SizeParameters pr
193193
* but we must still ensure that computations can handle it (for example, no overflows).
194194
*/
195195
survivorSize = UnsignedUtils.min(survivorSize, params.maxSurvivorSize());
196-
edenSize = UnsignedUtils.min(edenSize, maxEdenSize());
196+
edenSize = UnsignedUtils.min(edenSize, getMaximumEdenSize());
197197
oldSize = UnsignedUtils.min(oldSize, params.maxOldSize());
198198
promoSize = UnsignedUtils.min(promoSize, params.maxOldSize());
199199
}
200200

201+
@Override
202+
public UnsignedWord getInitialEdenSize() {
203+
guaranteeSizeParametersInitialized();
204+
return sizes.initialEdenSize;
205+
}
206+
207+
@Override
201208
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
202-
protected UnsignedWord maxEdenSize() {
209+
public UnsignedWord getMaximumEdenSize() {
210+
guaranteeSizeParametersInitialized();
203211
return alignDown(sizes.maxYoungSize.subtract(survivorSize.multiply(2)));
204212
}
205213

@@ -215,6 +223,18 @@ public UnsignedWord getMaximumYoungGenerationSize() {
215223
return sizes.maxYoungSize;
216224
}
217225

226+
@Override
227+
public UnsignedWord getInitialSurvivorSize() {
228+
guaranteeSizeParametersInitialized();
229+
return sizes.initialSurvivorSize;
230+
}
231+
232+
@Override
233+
public UnsignedWord getMaximumSurvivorSize() {
234+
guaranteeSizeParametersInitialized();
235+
return sizes.maxSurvivorSize();
236+
}
237+
218238
@Override
219239
public UnsignedWord getCurrentHeapCapacity() {
220240
assert VMOperation.isGCInProgress() : "use only during GC";
@@ -236,6 +256,18 @@ public UnsignedWord getYoungGenerationCapacity() {
236256
return edenSize.add(survivorSize);
237257
}
238258

259+
@Override
260+
public UnsignedWord getInitialOldSize() {
261+
guaranteeSizeParametersInitialized();
262+
return sizes.initialOldSize();
263+
}
264+
265+
@Override
266+
public UnsignedWord getMaximumOldSize() {
267+
guaranteeSizeParametersInitialized();
268+
return sizes.maxOldSize();
269+
}
270+
239271
@Override
240272
public UnsignedWord getOldGenerationCapacity() {
241273
guaranteeSizeParametersInitialized();
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved.
3+
* Copyright (c) 2023, 2023, BELLSOFT. All rights reserved.
4+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation. Oracle designates this
9+
* particular file as subject to the "Classpath" exception as provided
10+
* by Oracle in the LICENSE file that accompanied this code.
11+
*
12+
* This code is distributed in the hope that it will be useful, but WITHOUT
13+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15+
* version 2 for more details (a copy is included in the LICENSE file that
16+
* accompanied this code).
17+
*
18+
* You should have received a copy of the GNU General Public License version
19+
* 2 along with this work; if not, write to the Free Software Foundation,
20+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
21+
*
22+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
23+
* or visit www.oracle.com if you need additional information or have any
24+
* questions.
25+
*/
26+
package com.oracle.svm.core.genscavenge;
27+
28+
import java.lang.management.ManagementFactory;
29+
import java.lang.management.MemoryPoolMXBean;
30+
import java.lang.management.MemoryType;
31+
import java.lang.management.MemoryUsage;
32+
import java.util.Arrays;
33+
34+
import javax.management.ObjectName;
35+
36+
import org.graalvm.nativeimage.Platform;
37+
import org.graalvm.nativeimage.Platforms;
38+
import org.graalvm.word.UnsignedWord;
39+
import org.graalvm.word.WordFactory;
40+
41+
import com.oracle.svm.core.heap.AbstractMXBean;
42+
import com.oracle.svm.core.jdk.UninterruptibleUtils;
43+
44+
import sun.management.Util;
45+
46+
public abstract class AbstractMemoryPoolMXBean extends AbstractMXBean implements MemoryPoolMXBean {
47+
48+
private final String name;
49+
private final String[] managerNames;
50+
protected final UninterruptibleUtils.AtomicUnsigned peakUsage = new UninterruptibleUtils.AtomicUnsigned();
51+
52+
private static final UnsignedWord UNDEFINED = WordFactory.zero();
53+
protected UnsignedWord initialValue = UNDEFINED;
54+
55+
@Platforms(Platform.HOSTED_ONLY.class)
56+
protected AbstractMemoryPoolMXBean(String name, String... managerNames) {
57+
this.name = name;
58+
this.managerNames = managerNames;
59+
}
60+
61+
UnsignedWord getInitialValue() {
62+
if (initialValue.equal(UNDEFINED)) {
63+
initialValue = computeInitialValue();
64+
}
65+
return initialValue;
66+
}
67+
68+
abstract UnsignedWord computeInitialValue();
69+
70+
abstract UnsignedWord getMaximumValue();
71+
72+
abstract void afterCollection(GCAccounting accounting);
73+
74+
MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) {
75+
return new MemoryUsage(getInitialValue().rawValue(), usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), getMaximumValue().rawValue());
76+
}
77+
78+
MemoryUsage memoryUsage(UnsignedWord used, UnsignedWord committed) {
79+
return new MemoryUsage(getInitialValue().rawValue(), used.rawValue(), committed.rawValue(), getMaximumValue().rawValue());
80+
}
81+
82+
@Override
83+
public String getName() {
84+
return name;
85+
}
86+
87+
@Override
88+
public String[] getMemoryManagerNames() {
89+
return Arrays.copyOf(managerNames, managerNames.length);
90+
}
91+
92+
@Override
93+
public ObjectName getObjectName() {
94+
return Util.newObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + name);
95+
}
96+
97+
@Override
98+
public MemoryType getType() {
99+
return MemoryType.HEAP;
100+
}
101+
102+
@Override
103+
public boolean isValid() {
104+
return true;
105+
}
106+
107+
@Override
108+
public boolean isUsageThresholdSupported() {
109+
return false;
110+
}
111+
112+
@Override
113+
public long getUsageThreshold() {
114+
throw new UnsupportedOperationException("Usage threshold is not supported");
115+
}
116+
117+
@Override
118+
public void setUsageThreshold(long l) {
119+
throw new UnsupportedOperationException("Usage threshold is not supported");
120+
}
121+
122+
@Override
123+
public boolean isUsageThresholdExceeded() {
124+
throw new UnsupportedOperationException("Usage threshold is not supported");
125+
}
126+
127+
@Override
128+
public long getUsageThresholdCount() {
129+
throw new UnsupportedOperationException("Usage threshold is not supported");
130+
}
131+
132+
@Override
133+
public boolean isCollectionUsageThresholdSupported() {
134+
return false;
135+
}
136+
137+
@Override
138+
public long getCollectionUsageThreshold() {
139+
throw new UnsupportedOperationException("Collection usage threshold is not supported");
140+
}
141+
142+
@Override
143+
public void setCollectionUsageThreshold(long l) {
144+
throw new UnsupportedOperationException("Collection usage threshold is not supported");
145+
}
146+
147+
@Override
148+
public boolean isCollectionUsageThresholdExceeded() {
149+
throw new UnsupportedOperationException("Collection usage threshold is not supported");
150+
}
151+
152+
@Override
153+
public long getCollectionUsageThresholdCount() {
154+
throw new UnsupportedOperationException("Collection usage threshold is not supported");
155+
}
156+
157+
@Override
158+
public void resetPeakUsage() {
159+
peakUsage.set(WordFactory.zero());
160+
}
161+
162+
void updatePeakUsage(UnsignedWord value) {
163+
UnsignedWord current;
164+
do {
165+
current = peakUsage.get();
166+
} while (value.aboveThan(current) && !peakUsage.compareAndSet(current, value));
167+
}
168+
}

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ protected void computeEdenSpaceSize(@SuppressWarnings("unused") boolean complete
270270
assert isAligned(desiredEdenSize);
271271
desiredEdenSize = minSpaceSize(desiredEdenSize);
272272

273-
UnsignedWord edenLimit = maxEdenSize();
273+
UnsignedWord edenLimit = getMaximumEdenSize();
274274
if (desiredEdenSize.aboveThan(edenLimit)) {
275275
/*
276276
* If the policy says to get a larger eden but is hitting the limit, don't decrease

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,16 @@ public void updateSizeParameters() {
8787
// Size parameters are recomputed from current values whenever they are queried
8888
}
8989

90+
@Override
91+
public UnsignedWord getInitialEdenSize() {
92+
return UNDEFINED;
93+
}
94+
95+
@Override
96+
public UnsignedWord getMaximumEdenSize() {
97+
return getMaximumYoungGenerationSize();
98+
}
99+
90100
@Override
91101
public final UnsignedWord getMaximumHeapSize() {
92102
long runtimeValue = SubstrateGCOptions.MaxHeapSize.getValue();
@@ -146,6 +156,16 @@ public final UnsignedWord getMinimumHeapSize() {
146156
return result;
147157
}
148158

159+
@Override
160+
public UnsignedWord getInitialSurvivorSize() {
161+
return UNDEFINED;
162+
}
163+
164+
@Override
165+
public UnsignedWord getMaximumSurvivorSize() {
166+
return WordFactory.zero();
167+
}
168+
149169
@Override
150170
public UnsignedWord getSurvivorSpacesCapacity() {
151171
return WordFactory.zero();
@@ -156,6 +176,11 @@ public UnsignedWord getYoungGenerationCapacity() {
156176
return getMaximumYoungGenerationSize();
157177
}
158178

179+
@Override
180+
public UnsignedWord getInitialOldSize() {
181+
return UNDEFINED;
182+
}
183+
159184
@Override
160185
public UnsignedWord getOldGenerationCapacity() {
161186
UnsignedWord heapCapacity = getCurrentHeapCapacity();
@@ -166,6 +191,11 @@ public UnsignedWord getOldGenerationCapacity() {
166191
return heapCapacity.subtract(youngCapacity);
167192
}
168193

194+
@Override
195+
public UnsignedWord getMaximumOldSize() {
196+
return getOldGenerationCapacity();
197+
}
198+
169199
@Override
170200
public final UnsignedWord getMaximumFreeAlignedChunksSize() {
171201
return getMaximumYoungGenerationSize();

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.graalvm.nativeimage.Platform;
2828
import org.graalvm.nativeimage.Platforms;
2929
import org.graalvm.word.UnsignedWord;
30+
import org.graalvm.word.WordFactory;
3031

3132
import com.oracle.svm.core.SubstrateOptions;
3233
import com.oracle.svm.core.heap.GCCause;
@@ -36,6 +37,8 @@
3637

3738
/** The interface for a garbage collection policy. All sizes are in bytes. */
3839
public interface CollectionPolicy {
40+
UnsignedWord UNDEFINED = WordFactory.unsigned(-1);
41+
3942
@Platforms(Platform.HOSTED_ONLY.class)
4043
static String getInitialPolicyName() {
4144
if (SubstrateOptions.UseEpsilonGC.getValue()) {
@@ -143,6 +146,11 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
143146
*/
144147
UnsignedWord getCurrentHeapCapacity();
145148

149+
/** May be {@link #UNDEFINED}. */
150+
UnsignedWord getInitialEdenSize();
151+
152+
UnsignedWord getMaximumEdenSize();
153+
146154
/**
147155
* The hard limit for the size of the entire heap. Exceeding this limit triggers an
148156
* {@link OutOfMemoryError}.
@@ -158,6 +166,11 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
158166
/** The minimum heap size, for inclusion in diagnostic output. */
159167
UnsignedWord getMinimumHeapSize();
160168

169+
/** May be {@link #UNDEFINED}. */
170+
UnsignedWord getInitialSurvivorSize();
171+
172+
UnsignedWord getMaximumSurvivorSize();
173+
161174
/**
162175
* The total capacity of all survivor-from spaces of all ages, equal to the size of all
163176
* survivor-to spaces of all ages. In other words, when copying during a collection, up to 2x
@@ -168,9 +181,14 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
168181
/** The capacity of the young generation, comprising the eden and survivor spaces. */
169182
UnsignedWord getYoungGenerationCapacity();
170183

184+
/** May be {@link #UNDEFINED}. */
185+
UnsignedWord getInitialOldSize();
186+
171187
/** The capacity of the old generation. */
172188
UnsignedWord getOldGenerationCapacity();
173189

190+
UnsignedWord getMaximumOldSize();
191+
174192
/**
175193
* The maximum number of bytes that should be kept readily available for allocation or copying
176194
* during collections.
@@ -189,5 +207,4 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) {
189207

190208
/** Called before the end of a collection, in the safepoint operation. */
191209
void onCollectionEnd(boolean completeCollection, GCCause cause);
192-
193210
}

0 commit comments

Comments
 (0)