From 84ac64f1a2a2c1678c5c918c402c1f615da882ae Mon Sep 17 00:00:00 2001 From: peterz Date: Tue, 15 Nov 2022 17:06:56 +0300 Subject: [PATCH 01/14] Basic MemoryPoolMXBean implementation --- .../OldGenerationMemoryPoolMXBean.java | 51 ++++++ .../YoungGenerationMemoryPoolMXBean.java | 50 ++++++ .../graal/GenScavengeGCFeature.java | 3 + .../svm/core/heap/AbstractMemoryMXBean.java | 24 +-- .../core/heap/AbstractMemoryPoolMXBean.java | 145 ++++++++++++++++++ .../com/oracle/svm/core/heap/MXBeanBase.java | 53 +++++++ 6 files changed, 303 insertions(+), 23 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java create mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java new file mode 100644 index 000000000000..e783d29c284f --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.genscavenge; + +import java.lang.management.MemoryUsage; + +import com.oracle.svm.core.heap.AbstractMemoryPoolMXBean; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +/** + * A MemoryPoolMXBean for the old generation. + */ +public final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { + + @Platforms(Platform.HOSTED_ONLY.class) + public OldGenerationMemoryPoolMXBean() { + super("old generation"); + } + + @Override + public MemoryUsage getUsage() { + long used = HeapImpl.getHeapImpl().getOldGeneration().getChunkBytes().rawValue(); + long maxHeap = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); + long maxYoung = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); + return new MemoryUsage(UNDEFINED_MEMORY_USAGE, used, used, maxHeap - maxYoung); + } +} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java new file mode 100644 index 000000000000..82c29b18f5bb --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.genscavenge; + +import java.lang.management.MemoryUsage; + +import com.oracle.svm.core.heap.AbstractMemoryPoolMXBean; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +/** + * A MemoryPoolMXBean for the young generation. + */ +public final class YoungGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { + + @Platforms(Platform.HOSTED_ONLY.class) + public YoungGenerationMemoryPoolMXBean() { + super("young generation"); + } + + @Override + public MemoryUsage getUsage() { + long used = HeapImpl.getHeapImpl().getAccounting().getYoungUsedBytes().rawValue(); + long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); + return new MemoryUsage(UNDEFINED_MEMORY_USAGE, used, used, max); + } +} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index fbeddc93b71c..0a60ac9be223 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -28,6 +28,8 @@ import java.util.List; import java.util.Map; +import com.oracle.svm.core.genscavenge.OldGenerationMemoryPoolMXBean; +import com.oracle.svm.core.genscavenge.YoungGenerationMemoryPoolMXBean; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; @@ -92,6 +94,7 @@ public void duringSetup(DuringSetupAccess access) { ManagementSupport managementSupport = ManagementSupport.getSingleton(); managementSupport.addPlatformManagedObjectSingleton(java.lang.management.MemoryMXBean.class, new HeapImplMemoryMXBean()); + managementSupport.addPlatformManagedObjectList(java.lang.management.MemoryPoolMXBean.class, Arrays.asList(new YoungGenerationMemoryPoolMXBean(), new OldGenerationMemoryPoolMXBean())); managementSupport.addPlatformManagedObjectList(com.sun.management.GarbageCollectorMXBean.class, Arrays.asList(new IncrementalGarbageCollectorMXBean(), new CompleteGarbageCollectorMXBean())); if (ImageSingletons.contains(PerfManager.class)) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java index eca682c9d79f..99c416002cd6 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java @@ -28,10 +28,6 @@ import java.lang.management.MemoryMXBean; import java.lang.management.MemoryUsage; -import javax.management.MBeanNotificationInfo; -import javax.management.NotificationEmitter; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; import javax.management.ObjectName; import org.graalvm.nativeimage.Platform; @@ -48,8 +44,7 @@ import sun.management.Util; -public abstract class AbstractMemoryMXBean implements MemoryMXBean, NotificationEmitter { - protected static final long UNDEFINED_MEMORY_USAGE = -1L; +public abstract class AbstractMemoryMXBean extends MXBeanBase implements MemoryMXBean { private final MemoryMXBeanCodeInfoVisitor codeInfoVisitor; @@ -93,23 +88,6 @@ public void gc() { System.gc(); } - @Override - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { - } - - @Override - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { - } - - @Override - public void removeNotificationListener(NotificationListener listener) { - } - - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - return new MBeanNotificationInfo[0]; - } - private static final class MemoryMXBeanCodeInfoVisitor implements CodeInfoVisitor { private UnsignedWord runtimeCodeInfoSize; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java new file mode 100644 index 000000000000..12029763af36 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.heap; + +import javax.management.ObjectName; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryType; +import java.lang.management.MemoryUsage; + +import sun.management.Util; + +public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements MemoryPoolMXBean { + + protected final String name; + protected final String managerName; + protected final String objectName; + + protected MemoryUsage peakUsage = new MemoryUsage(0L, 0L, 0L, 0L); + + protected AbstractMemoryPoolMXBean(String managerName) { + this.managerName = managerName; + this.name = this.managerName + " space"; + this.objectName = ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + this.name; + } + + @Override + public String getName() { + return name; + } + + @Override + public String[] getMemoryManagerNames() { + return new String[] { managerName }; + } + + @Override + public ObjectName getObjectName() { + return Util.newObjectName(objectName); + } + + @Override + public MemoryType getType() { + return MemoryType.HEAP; + } + + @Override + public boolean isValid() { + return true; + } + + @Override + public MemoryUsage getPeakUsage() { + MemoryUsage curUsage = getUsage(); + long peakInit = Math.max(peakUsage.getInit(), curUsage.getInit()); + long peakUsed = Math.max(peakUsage.getUsed(), curUsage.getUsed()); + long peakCommitted = Math.max(peakUsage.getCommitted(), curUsage.getCommitted()); + long peakMax = Math.max(peakUsage.getMax(), curUsage.getMax()); + peakUsage = new MemoryUsage(peakInit, peakUsed, peakCommitted, peakMax); + return peakUsage; + } + + @Override + public void resetPeakUsage() { + peakUsage = getUsage(); + } + + @Override + public MemoryUsage getCollectionUsage() { + return null; + } + + @Override + public boolean isUsageThresholdSupported() { + return false; + } + + @Override + public long getUsageThreshold() { + throw new UnsupportedOperationException("Usage threshold is not supported"); + } + + @Override + public void setUsageThreshold(long l) { + throw new UnsupportedOperationException("Usage threshold is not supported"); + } + + @Override + public boolean isUsageThresholdExceeded() { + throw new UnsupportedOperationException("Usage threshold is not supported"); + } + + @Override + public long getUsageThresholdCount() { + throw new UnsupportedOperationException("Usage threshold is not supported"); + } + + @Override + public boolean isCollectionUsageThresholdSupported() { + return false; + } + + @Override + public long getCollectionUsageThreshold() { + throw new UnsupportedOperationException("Collection usage threshold is not supported"); + } + + @Override + public void setCollectionUsageThreshold(long l) { + throw new UnsupportedOperationException("Collection usage threshold is not supported"); + } + + @Override + public boolean isCollectionUsageThresholdExceeded() { + throw new UnsupportedOperationException("Collection usage threshold is not supported"); + } + + @Override + public long getCollectionUsageThresholdCount() { + throw new UnsupportedOperationException("Collection usage threshold is not supported"); + } +} \ No newline at end of file diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java new file mode 100644 index 000000000000..d8d114576001 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.heap; + +import javax.management.MBeanNotificationInfo; +import javax.management.NotificationEmitter; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; + +public class MXBeanBase implements NotificationEmitter { + + protected static final long UNDEFINED_MEMORY_USAGE = -1L; + + @Override + public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { + } + + @Override + public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { + } + + @Override + public void removeNotificationListener(NotificationListener listener) { + } + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + return new MBeanNotificationInfo[0]; + } +} From cb9e2672f5d6bc1c69ef7b24ff0290883a673a65 Mon Sep 17 00:00:00 2001 From: peterz Date: Wed, 16 Nov 2022 12:31:53 +0300 Subject: [PATCH 02/14] Implemented `getPeakUsage()` --- .../svm/core/genscavenge/GCAccounting.java | 27 +++++++++++++++++++ .../OldGenerationMemoryPoolMXBean.java | 19 +++++++++++-- .../YoungGenerationMemoryPoolMXBean.java | 25 ++++++++++++++--- .../core/heap/AbstractMemoryPoolMXBean.java | 18 ------------- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index e556ce773b81..708eea6c016e 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -24,6 +24,8 @@ */ package com.oracle.svm.core.genscavenge; +import com.oracle.svm.core.jdk.UninterruptibleUtils; +import com.oracle.svm.core.util.UnsignedUtils; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.UnsignedWord; @@ -55,6 +57,9 @@ public final class GCAccounting { private UnsignedWord oldChunkBytesBefore = WordFactory.zero(); private UnsignedWord oldChunkBytesAfter = WordFactory.zero(); + private final UninterruptibleUtils.AtomicUnsigned peakYoungChunkBytes = new UninterruptibleUtils.AtomicUnsigned(); + private final UninterruptibleUtils.AtomicUnsigned peakOldChunkBytes = new UninterruptibleUtils.AtomicUnsigned(); + /* * Bytes allocated in Objects, as opposed to bytes of chunks. These are only maintained if * -R:+PrintGCSummary because they are expensive. @@ -112,6 +117,22 @@ UnsignedWord getYoungChunkBytesAfter() { return youngChunkBytesAfter; } + UnsignedWord getPeakYoungChunkBytes() { + return peakYoungChunkBytes.get(); + } + + UnsignedWord getPeakOldChunkBytes() { + return peakOldChunkBytes.get(); + } + + void resetPeakYoungChunkBytes() { + peakYoungChunkBytes.set(WordFactory.zero()); + } + + void resetPeakOldChunkBytes() { + peakOldChunkBytes.set(WordFactory.zero()); + } + UnsignedWord getLastIncrementalCollectionPromotedChunkBytes() { return lastIncrementalCollectionPromotedChunkBytes; } @@ -126,9 +147,11 @@ void beforeCollection(boolean completeCollection) { HeapImpl heap = HeapImpl.getHeapImpl(); YoungGeneration youngGen = heap.getYoungGeneration(); youngChunkBytesBefore = youngGen.getChunkBytes(); + updatePeakValue(peakYoungChunkBytes, youngChunkBytesBefore); /* This is called before the collection, so OldSpace is FromSpace. */ Space oldSpace = heap.getOldGeneration().getFromSpace(); oldChunkBytesBefore = oldSpace.getChunkBytes(); + updatePeakValue(peakOldChunkBytes, oldChunkBytesBefore); /* Objects are allocated in the young generation. */ allocatedChunkBytes = allocatedChunkBytes.add(youngGen.getEden().getChunkBytes()); if (SerialGCOptions.PrintGCSummary.getValue()) { @@ -205,4 +228,8 @@ private void afterCollectionCommon() { collectedTotalObjectBytes = collectedTotalObjectBytes.add(collectedObjectBytes); } } + + private void updatePeakValue(UninterruptibleUtils.AtomicUnsigned peakValue, UnsignedWord currentValue) { + peakValue.set(UnsignedUtils.max(peakValue.get(), currentValue)); + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java index e783d29c284f..01570c04f062 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java @@ -44,8 +44,23 @@ public OldGenerationMemoryPoolMXBean() { @Override public MemoryUsage getUsage() { long used = HeapImpl.getHeapImpl().getOldGeneration().getChunkBytes().rawValue(); + return memoryUsage(used); + } + + @Override + public MemoryUsage getPeakUsage() { + long peak = GCImpl.getGCImpl().getAccounting().getPeakOldChunkBytes().rawValue(); + return memoryUsage(peak); + } + + @Override + public void resetPeakUsage() { + GCImpl.getGCImpl().getAccounting().resetPeakOldChunkBytes(); + } + + private MemoryUsage memoryUsage(long usedAndCommitted) { long maxHeap = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); - long maxYoung = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); - return new MemoryUsage(UNDEFINED_MEMORY_USAGE, used, used, maxHeap - maxYoung); + long maxYoung = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue();///const? + return new MemoryUsage(UNDEFINED_MEMORY_USAGE, usedAndCommitted, usedAndCommitted, maxHeap - maxYoung); } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java index 82c29b18f5bb..a3dd5122dfbb 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java @@ -43,8 +43,27 @@ public YoungGenerationMemoryPoolMXBean() { @Override public MemoryUsage getUsage() { - long used = HeapImpl.getHeapImpl().getAccounting().getYoungUsedBytes().rawValue(); - long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); - return new MemoryUsage(UNDEFINED_MEMORY_USAGE, used, used, max); + return memoryUsage(getCurrentUsage()); + } + + @Override + public MemoryUsage getPeakUsage() { + long current = getCurrentUsage(); + long peak = GCImpl.getGCImpl().getAccounting().getPeakYoungChunkBytes().rawValue(); + return memoryUsage(Math.max(current, peak)); + } + + @Override + public void resetPeakUsage() { + GCImpl.getGCImpl().getAccounting().resetPeakYoungChunkBytes(); + } + + private long getCurrentUsage() { + return HeapImpl.getHeapImpl().getAccounting().getYoungUsedBytes().rawValue(); + } + + private MemoryUsage memoryUsage(long usedAndCommitted) { + long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue();///const? + return new MemoryUsage(UNDEFINED_MEMORY_USAGE, usedAndCommitted, usedAndCommitted, max); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java index 12029763af36..295dc71cfee7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java @@ -39,8 +39,6 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements Mem protected final String managerName; protected final String objectName; - protected MemoryUsage peakUsage = new MemoryUsage(0L, 0L, 0L, 0L); - protected AbstractMemoryPoolMXBean(String managerName) { this.managerName = managerName; this.name = this.managerName + " space"; @@ -72,22 +70,6 @@ public boolean isValid() { return true; } - @Override - public MemoryUsage getPeakUsage() { - MemoryUsage curUsage = getUsage(); - long peakInit = Math.max(peakUsage.getInit(), curUsage.getInit()); - long peakUsed = Math.max(peakUsage.getUsed(), curUsage.getUsed()); - long peakCommitted = Math.max(peakUsage.getCommitted(), curUsage.getCommitted()); - long peakMax = Math.max(peakUsage.getMax(), curUsage.getMax()); - peakUsage = new MemoryUsage(peakInit, peakUsed, peakCommitted, peakMax); - return peakUsage; - } - - @Override - public void resetPeakUsage() { - peakUsage = getUsage(); - } - @Override public MemoryUsage getCollectionUsage() { return null; From 3cd5696f1028c965479acc8da271bb3713f76adc Mon Sep 17 00:00:00 2001 From: peterz Date: Wed, 16 Nov 2022 14:44:29 +0300 Subject: [PATCH 03/14] Better mempool names --- .../genscavenge/OldGenerationMemoryPoolMXBean.java | 4 ++-- .../genscavenge/YoungGenerationMemoryPoolMXBean.java | 4 ++-- .../svm/core/heap/AbstractMemoryPoolMXBean.java | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java index 01570c04f062..601c00eed76e 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java @@ -38,7 +38,7 @@ public final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBea @Platforms(Platform.HOSTED_ONLY.class) public OldGenerationMemoryPoolMXBean() { - super("old generation"); + super("old generation space", "complete scavenger"); } @Override @@ -60,7 +60,7 @@ public void resetPeakUsage() { private MemoryUsage memoryUsage(long usedAndCommitted) { long maxHeap = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); - long maxYoung = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue();///const? + long maxYoung = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); return new MemoryUsage(UNDEFINED_MEMORY_USAGE, usedAndCommitted, usedAndCommitted, maxHeap - maxYoung); } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java index a3dd5122dfbb..ce06816de591 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java @@ -38,7 +38,7 @@ public final class YoungGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXB @Platforms(Platform.HOSTED_ONLY.class) public YoungGenerationMemoryPoolMXBean() { - super("young generation"); + super("young generation space", "young generation scavenger", "complete scavenger"); } @Override @@ -63,7 +63,7 @@ private long getCurrentUsage() { } private MemoryUsage memoryUsage(long usedAndCommitted) { - long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue();///const? + long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); return new MemoryUsage(UNDEFINED_MEMORY_USAGE, usedAndCommitted, usedAndCommitted, max); } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java index 295dc71cfee7..c0c012cffb9f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java @@ -36,13 +36,13 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements MemoryPoolMXBean { protected final String name; - protected final String managerName; + protected final String[] managerNames; protected final String objectName; - protected AbstractMemoryPoolMXBean(String managerName) { - this.managerName = managerName; - this.name = this.managerName + " space"; - this.objectName = ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + this.name; + protected AbstractMemoryPoolMXBean(String name, String... managerNames) { + this.name = name; + this.managerNames = managerNames.clone(); + this.objectName = ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + name; } @Override @@ -52,7 +52,7 @@ public String getName() { @Override public String[] getMemoryManagerNames() { - return new String[] { managerName }; + return managerNames.clone(); } @Override From 5a1723e4e05f72e409625c3bd44a6b0a8fe247c1 Mon Sep 17 00:00:00 2001 From: peterz Date: Thu, 17 Nov 2022 14:15:03 +0300 Subject: [PATCH 04/14] Implemented `getCollectionUsage()` --- .../genscavenge}/AbstractMemoryPoolMXBean.java | 5 ++++- .../OldGenerationMemoryPoolMXBean.java | 18 ++++++++++++------ .../YoungGenerationMemoryPoolMXBean.java | 13 +++++++++---- 3 files changed, 25 insertions(+), 11 deletions(-) rename substratevm/src/{com.oracle.svm.core/src/com/oracle/svm/core/heap => com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge}/AbstractMemoryPoolMXBean.java (95%) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java similarity index 95% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java rename to substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index c0c012cffb9f..8eadc2a501ff 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -23,7 +23,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.heap; +package com.oracle.svm.core.genscavenge; import javax.management.ObjectName; import java.lang.management.ManagementFactory; @@ -31,6 +31,7 @@ import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; +import com.oracle.svm.core.heap.MXBeanBase; import sun.management.Util; public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements MemoryPoolMXBean { @@ -38,11 +39,13 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements Mem protected final String name; protected final String[] managerNames; protected final String objectName; + protected final GCAccounting gcAccounting; protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.name = name; this.managerNames = managerNames.clone(); this.objectName = ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + name; + this.gcAccounting = GCImpl.getGCImpl().getAccounting(); } @Override diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java index 601c00eed76e..cfd6fb48fdfa 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java @@ -27,7 +27,6 @@ import java.lang.management.MemoryUsage; -import com.oracle.svm.core.heap.AbstractMemoryPoolMXBean; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -49,18 +48,25 @@ public MemoryUsage getUsage() { @Override public MemoryUsage getPeakUsage() { - long peak = GCImpl.getGCImpl().getAccounting().getPeakOldChunkBytes().rawValue(); + long peak = gcAccounting.getPeakOldChunkBytes().rawValue(); return memoryUsage(peak); } @Override public void resetPeakUsage() { - GCImpl.getGCImpl().getAccounting().resetPeakOldChunkBytes(); + gcAccounting.resetPeakOldChunkBytes(); + } + + @Override + public MemoryUsage getCollectionUsage() { + long used = gcAccounting.getOldGenerationAfterChunkBytes().rawValue(); + return memoryUsage(used); } private MemoryUsage memoryUsage(long usedAndCommitted) { - long maxHeap = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); - long maxYoung = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); - return new MemoryUsage(UNDEFINED_MEMORY_USAGE, usedAndCommitted, usedAndCommitted, maxHeap - maxYoung); + CollectionPolicy policy = GCImpl.getPolicy(); + long maxHeap = policy.getMaximumHeapSize().rawValue(); + long maxYoung = policy.getMaximumYoungGenerationSize().rawValue(); + return new MemoryUsage(0L, usedAndCommitted, usedAndCommitted, maxHeap - maxYoung); } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java index ce06816de591..2cf6b6c24026 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java @@ -27,7 +27,6 @@ import java.lang.management.MemoryUsage; -import com.oracle.svm.core.heap.AbstractMemoryPoolMXBean; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -49,13 +48,19 @@ public MemoryUsage getUsage() { @Override public MemoryUsage getPeakUsage() { long current = getCurrentUsage(); - long peak = GCImpl.getGCImpl().getAccounting().getPeakYoungChunkBytes().rawValue(); + long peak = gcAccounting.getPeakYoungChunkBytes().rawValue(); return memoryUsage(Math.max(current, peak)); } @Override public void resetPeakUsage() { - GCImpl.getGCImpl().getAccounting().resetPeakYoungChunkBytes(); + gcAccounting.resetPeakYoungChunkBytes(); + } + + @Override + public MemoryUsage getCollectionUsage() { + long used = gcAccounting.getYoungChunkBytesAfter().rawValue(); + return memoryUsage(used); } private long getCurrentUsage() { @@ -64,6 +69,6 @@ private long getCurrentUsage() { private MemoryUsage memoryUsage(long usedAndCommitted) { long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); - return new MemoryUsage(UNDEFINED_MEMORY_USAGE, usedAndCommitted, usedAndCommitted, max); + return new MemoryUsage(0L, usedAndCommitted, usedAndCommitted, max); } } From d67a3010ab6cedbd7c66f6ac2b4e1465146a68bb Mon Sep 17 00:00:00 2001 From: peterz Date: Mon, 21 Nov 2022 10:13:29 +0300 Subject: [PATCH 05/14] Style fixes --- .../svm/core/genscavenge/AbstractMemoryPoolMXBean.java | 4 ++-- .../src/com/oracle/svm/core/genscavenge/GCAccounting.java | 2 +- .../svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java | 4 ++-- .../core/genscavenge/YoungGenerationMemoryPoolMXBean.java | 6 +++--- .../src/com/oracle/svm/core/heap/MXBeanBase.java | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index 8eadc2a501ff..ade24d9025f3 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,4 +127,4 @@ public boolean isCollectionUsageThresholdExceeded() { public long getCollectionUsageThresholdCount() { throw new UnsupportedOperationException("Collection usage threshold is not supported"); } -} \ No newline at end of file +} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index 708eea6c016e..34983872ee7d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -229,7 +229,7 @@ private void afterCollectionCommon() { } } - private void updatePeakValue(UninterruptibleUtils.AtomicUnsigned peakValue, UnsignedWord currentValue) { + private static void updatePeakValue(UninterruptibleUtils.AtomicUnsigned peakValue, UnsignedWord currentValue) { peakValue.set(UnsignedUtils.max(peakValue.get(), currentValue)); } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java index cfd6fb48fdfa..bf8e0f75ae66 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,7 +63,7 @@ public MemoryUsage getCollectionUsage() { return memoryUsage(used); } - private MemoryUsage memoryUsage(long usedAndCommitted) { + private static MemoryUsage memoryUsage(long usedAndCommitted) { CollectionPolicy policy = GCImpl.getPolicy(); long maxHeap = policy.getMaximumHeapSize().rawValue(); long maxYoung = policy.getMaximumYoungGenerationSize().rawValue(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java index 2cf6b6c24026..d1823fecb513 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,11 +63,11 @@ public MemoryUsage getCollectionUsage() { return memoryUsage(used); } - private long getCurrentUsage() { + private static long getCurrentUsage() { return HeapImpl.getHeapImpl().getAccounting().getYoungUsedBytes().rawValue(); } - private MemoryUsage memoryUsage(long usedAndCommitted) { + private static MemoryUsage memoryUsage(long usedAndCommitted) { long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); return new MemoryUsage(0L, usedAndCommitted, usedAndCommitted, max); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java index d8d114576001..6eef37003ee8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From d1a3393be4c1da7a069331176d6a678ff24c70a2 Mon Sep 17 00:00:00 2001 From: peterz Date: Thu, 16 Feb 2023 13:06:01 +0300 Subject: [PATCH 06/14] Post review cleanup --- .../core/genscavenge/AbstractMemoryPoolMXBean.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index ade24d9025f3..89752190aa69 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -30,21 +30,23 @@ import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; +import java.util.Arrays; import com.oracle.svm.core.heap.MXBeanBase; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; import sun.management.Util; +@Platforms(Platform.HOSTED_ONLY.class) public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements MemoryPoolMXBean { protected final String name; protected final String[] managerNames; - protected final String objectName; protected final GCAccounting gcAccounting; protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.name = name; - this.managerNames = managerNames.clone(); - this.objectName = ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + name; + this.managerNames = managerNames; this.gcAccounting = GCImpl.getGCImpl().getAccounting(); } @@ -55,12 +57,12 @@ public String getName() { @Override public String[] getMemoryManagerNames() { - return managerNames.clone(); + return Arrays.copyOf(managerNames, managerNames.length); } @Override public ObjectName getObjectName() { - return Util.newObjectName(objectName); + return Util.newObjectName(ManagementFactory.MEMORY_POOL_MXBEAN_DOMAIN_TYPE + ",name=" + name); } @Override From d98f7b541be4b6bfe7f70956bea64f6c939a43af Mon Sep 17 00:00:00 2001 From: peterz Date: Fri, 17 Feb 2023 17:28:32 +0300 Subject: [PATCH 07/14] Moved peak data from GCAccounting into AbstractMemoryPoolMXBean --- .../genscavenge/AbstractMemoryPoolMXBean.java | 22 +++++++--- .../svm/core/genscavenge/GCAccounting.java | 41 +++++++------------ .../OldGenerationMemoryPoolMXBean.java | 12 +++--- .../YoungGenerationMemoryPoolMXBean.java | 12 +++--- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index 89752190aa69..f7c631639a61 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -29,12 +29,15 @@ import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; -import java.lang.management.MemoryUsage; import java.util.Arrays; import com.oracle.svm.core.heap.MXBeanBase; +import com.oracle.svm.core.jdk.UninterruptibleUtils; +import com.oracle.svm.core.util.UnsignedUtils; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; import sun.management.Util; @Platforms(Platform.HOSTED_ONLY.class) @@ -43,6 +46,7 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements Mem protected final String name; protected final String[] managerNames; protected final GCAccounting gcAccounting; + protected final UninterruptibleUtils.AtomicUnsigned peakUsage = new UninterruptibleUtils.AtomicUnsigned(); protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.name = name; @@ -50,6 +54,8 @@ protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.gcAccounting = GCImpl.getGCImpl().getAccounting(); } + abstract void beforeCollection(); + @Override public String getName() { return name; @@ -75,11 +81,6 @@ public boolean isValid() { return true; } - @Override - public MemoryUsage getCollectionUsage() { - return null; - } - @Override public boolean isUsageThresholdSupported() { return false; @@ -129,4 +130,13 @@ public boolean isCollectionUsageThresholdExceeded() { public long getCollectionUsageThresholdCount() { throw new UnsupportedOperationException("Collection usage threshold is not supported"); } + + @Override + public void resetPeakUsage() { + peakUsage.set(WordFactory.zero()); + } + + void updatePeakUsage(UnsignedWord currentValue) { + peakUsage.set(UnsignedUtils.max(peakUsage.get(), currentValue)); + } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index 34983872ee7d..98b650988d45 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -24,8 +24,6 @@ */ package com.oracle.svm.core.genscavenge; -import com.oracle.svm.core.jdk.UninterruptibleUtils; -import com.oracle.svm.core.util.UnsignedUtils; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.UnsignedWord; @@ -34,6 +32,9 @@ import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.log.Log; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; + /** * This data is only updated during a GC. * @@ -57,9 +58,6 @@ public final class GCAccounting { private UnsignedWord oldChunkBytesBefore = WordFactory.zero(); private UnsignedWord oldChunkBytesAfter = WordFactory.zero(); - private final UninterruptibleUtils.AtomicUnsigned peakYoungChunkBytes = new UninterruptibleUtils.AtomicUnsigned(); - private final UninterruptibleUtils.AtomicUnsigned peakOldChunkBytes = new UninterruptibleUtils.AtomicUnsigned(); - /* * Bytes allocated in Objects, as opposed to bytes of chunks. These are only maintained if * -R:+PrintGCSummary because they are expensive. @@ -109,6 +107,10 @@ public UnsignedWord getOldGenerationAfterChunkBytes() { return oldChunkBytesAfter; } + UnsignedWord getOldChunkBytesBefore() { + return oldChunkBytesBefore; + } + UnsignedWord getYoungChunkBytesBefore() { return youngChunkBytesBefore; } @@ -117,22 +119,6 @@ UnsignedWord getYoungChunkBytesAfter() { return youngChunkBytesAfter; } - UnsignedWord getPeakYoungChunkBytes() { - return peakYoungChunkBytes.get(); - } - - UnsignedWord getPeakOldChunkBytes() { - return peakOldChunkBytes.get(); - } - - void resetPeakYoungChunkBytes() { - peakYoungChunkBytes.set(WordFactory.zero()); - } - - void resetPeakOldChunkBytes() { - peakOldChunkBytes.set(WordFactory.zero()); - } - UnsignedWord getLastIncrementalCollectionPromotedChunkBytes() { return lastIncrementalCollectionPromotedChunkBytes; } @@ -141,17 +127,21 @@ public boolean hasLastIncrementalCollectionOverflowedSurvivors() { return lastIncrementalCollectionOverflowedSurvivors; } + void notifyMemoryPoolMXBeans() { + for (MemoryPoolMXBean bean: ManagementFactory.getPlatformMXBeans(MemoryPoolMXBean.class)) { + ((AbstractMemoryPoolMXBean)bean).beforeCollection(); + } + } + void beforeCollection(boolean completeCollection) { Log trace = Log.noopLog().string("[GCImpl.Accounting.beforeCollection:").newline(); /* Gather some space statistics. */ HeapImpl heap = HeapImpl.getHeapImpl(); YoungGeneration youngGen = heap.getYoungGeneration(); youngChunkBytesBefore = youngGen.getChunkBytes(); - updatePeakValue(peakYoungChunkBytes, youngChunkBytesBefore); /* This is called before the collection, so OldSpace is FromSpace. */ Space oldSpace = heap.getOldGeneration().getFromSpace(); oldChunkBytesBefore = oldSpace.getChunkBytes(); - updatePeakValue(peakOldChunkBytes, oldChunkBytesBefore); /* Objects are allocated in the young generation. */ allocatedChunkBytes = allocatedChunkBytes.add(youngGen.getEden().getChunkBytes()); if (SerialGCOptions.PrintGCSummary.getValue()) { @@ -163,6 +153,7 @@ void beforeCollection(boolean completeCollection) { if (!completeCollection) { lastIncrementalCollectionOverflowedSurvivors = false; } + notifyMemoryPoolMXBeans(); trace.string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); trace.string("]").newline(); @@ -228,8 +219,4 @@ private void afterCollectionCommon() { collectedTotalObjectBytes = collectedTotalObjectBytes.add(collectedObjectBytes); } } - - private static void updatePeakValue(UninterruptibleUtils.AtomicUnsigned peakValue, UnsignedWord currentValue) { - peakValue.set(UnsignedUtils.max(peakValue.get(), currentValue)); - } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java index bf8e0f75ae66..f173f9456d3d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java @@ -40,6 +40,11 @@ public OldGenerationMemoryPoolMXBean() { super("old generation space", "complete scavenger"); } + @Override + void beforeCollection() { + updatePeakUsage(gcAccounting.getOldChunkBytesBefore()); + } + @Override public MemoryUsage getUsage() { long used = HeapImpl.getHeapImpl().getOldGeneration().getChunkBytes().rawValue(); @@ -48,15 +53,10 @@ public MemoryUsage getUsage() { @Override public MemoryUsage getPeakUsage() { - long peak = gcAccounting.getPeakOldChunkBytes().rawValue(); + long peak = peakUsage.get().rawValue(); return memoryUsage(peak); } - @Override - public void resetPeakUsage() { - gcAccounting.resetPeakOldChunkBytes(); - } - @Override public MemoryUsage getCollectionUsage() { long used = gcAccounting.getOldGenerationAfterChunkBytes().rawValue(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java index d1823fecb513..3dc79ea62f6e 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java @@ -40,6 +40,11 @@ public YoungGenerationMemoryPoolMXBean() { super("young generation space", "young generation scavenger", "complete scavenger"); } + @Override + void beforeCollection() { + updatePeakUsage(gcAccounting.getYoungChunkBytesBefore()); + } + @Override public MemoryUsage getUsage() { return memoryUsage(getCurrentUsage()); @@ -48,15 +53,10 @@ public MemoryUsage getUsage() { @Override public MemoryUsage getPeakUsage() { long current = getCurrentUsage(); - long peak = gcAccounting.getPeakYoungChunkBytes().rawValue(); + long peak = peakUsage.get().rawValue(); return memoryUsage(Math.max(current, peak)); } - @Override - public void resetPeakUsage() { - gcAccounting.resetPeakYoungChunkBytes(); - } - @Override public MemoryUsage getCollectionUsage() { long used = gcAccounting.getYoungChunkBytesAfter().rawValue(); From c7650757519607f7429b863f68430f8df110ef31 Mon Sep 17 00:00:00 2001 From: peterz Date: Mon, 20 Feb 2023 18:51:32 +0300 Subject: [PATCH 08/14] Added eden, survivor, and epsilon beans --- .../genscavenge/AbstractCollectionPolicy.java | 6 + .../genscavenge/AbstractMemoryPoolMXBean.java | 4 +- .../genscavenge/BasicCollectionPolicies.java | 5 + .../core/genscavenge/CollectionPolicy.java | 2 + .../svm/core/genscavenge/GCAccounting.java | 22 +- .../core/genscavenge/MemoryPoolMXBeans.java | 214 ++++++++++++++++++ .../OldGenerationMemoryPoolMXBean.java | 72 ------ .../YoungGenerationMemoryPoolMXBean.java | 74 ------ .../graal/GenScavengeGCFeature.java | 5 +- 9 files changed, 238 insertions(+), 166 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java delete mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java delete mode 100644 substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index 082e2752c1df..f08de5099649 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -215,6 +215,12 @@ public UnsignedWord getMaximumYoungGenerationSize() { return sizes.maxYoungSize; } + @Override + public UnsignedWord getMaximumSurvivorSize() { + guaranteeSizeParametersInitialized(); + return sizes.maxSurvivorSize(); + } + @Override public UnsignedWord getCurrentHeapCapacity() { assert VMOperation.isGCInProgress() : "use only during GC"; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index f7c631639a61..8b760774a165 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -45,16 +45,14 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements Mem protected final String name; protected final String[] managerNames; - protected final GCAccounting gcAccounting; protected final UninterruptibleUtils.AtomicUnsigned peakUsage = new UninterruptibleUtils.AtomicUnsigned(); protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.name = name; this.managerNames = managerNames; - this.gcAccounting = GCImpl.getGCImpl().getAccounting(); } - abstract void beforeCollection(); + abstract void afterCollection(); @Override public String getName() { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java index 319f265fa49c..bb97ae75aabf 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java @@ -146,6 +146,11 @@ public final UnsignedWord getMinimumHeapSize() { return result; } + @Override + public UnsignedWord getMaximumSurvivorSize() { + return WordFactory.zero(); + } + @Override public UnsignedWord getSurvivorSpacesCapacity() { return WordFactory.zero(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java index 1739b5fada3d..182744716a64 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java @@ -151,6 +151,8 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) { /** The minimum heap size, for inclusion in diagnostic output. */ UnsignedWord getMinimumHeapSize(); + UnsignedWord getMaximumSurvivorSize(); + /** * The total capacity of all survivor-from spaces of all ages, equal to the size of all * survivor-to spaces of all ages. In other words, when copying during a collection, up to 2x diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index 98b650988d45..c2a658511314 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -32,9 +32,6 @@ import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.log.Log; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryPoolMXBean; - /** * This data is only updated during a GC. * @@ -53,6 +50,7 @@ public final class GCAccounting { private boolean lastIncrementalCollectionOverflowedSurvivors = false; /* Before and after measures. */ + private UnsignedWord edenChunkBytesBefore = WordFactory.zero(); private UnsignedWord youngChunkBytesBefore = WordFactory.zero(); private UnsignedWord youngChunkBytesAfter = WordFactory.zero(); private UnsignedWord oldChunkBytesBefore = WordFactory.zero(); @@ -107,8 +105,8 @@ public UnsignedWord getOldGenerationAfterChunkBytes() { return oldChunkBytesAfter; } - UnsignedWord getOldChunkBytesBefore() { - return oldChunkBytesBefore; + UnsignedWord getEdenChunkBytesBefore() { + return edenChunkBytesBefore; } UnsignedWord getYoungChunkBytesBefore() { @@ -127,17 +125,12 @@ public boolean hasLastIncrementalCollectionOverflowedSurvivors() { return lastIncrementalCollectionOverflowedSurvivors; } - void notifyMemoryPoolMXBeans() { - for (MemoryPoolMXBean bean: ManagementFactory.getPlatformMXBeans(MemoryPoolMXBean.class)) { - ((AbstractMemoryPoolMXBean)bean).beforeCollection(); - } - } - void beforeCollection(boolean completeCollection) { Log trace = Log.noopLog().string("[GCImpl.Accounting.beforeCollection:").newline(); /* Gather some space statistics. */ HeapImpl heap = HeapImpl.getHeapImpl(); YoungGeneration youngGen = heap.getYoungGeneration(); + edenChunkBytesBefore = youngGen.getEden().getChunkBytes(); youngChunkBytesBefore = youngGen.getChunkBytes(); /* This is called before the collection, so OldSpace is FromSpace. */ Space oldSpace = heap.getOldGeneration().getFromSpace(); @@ -153,9 +146,9 @@ void beforeCollection(boolean completeCollection) { if (!completeCollection) { lastIncrementalCollectionOverflowedSurvivors = false; } - notifyMemoryPoolMXBeans(); - trace.string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) - .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); + trace.string(" edenChunkBytesBefore: ").unsigned(edenChunkBytesBefore) + .string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) + .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); trace.string("]").newline(); } @@ -171,6 +164,7 @@ void afterCollection(boolean completeCollection, Timer collectionTimer) { } else { afterIncrementalCollection(collectionTimer); } + MemoryPoolMXBeans.notifyAfterCollection(); } private void afterIncrementalCollection(Timer collectionTimer) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java new file mode 100644 index 000000000000..1305e9e28a5b --- /dev/null +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.core.genscavenge; + +import com.oracle.svm.core.SubstrateOptions; +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; +import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; + +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryUsage; +import java.util.List; + +public class MemoryPoolMXBeans { + + private static AbstractMemoryPoolMXBean[] mxBeans; + + @Platforms(Platform.HOSTED_ONLY.class) + public static List createMemoryPoolMXBeans() { + List beanList; + if (SubstrateOptions.UseSerialGC.getValue()) { + beanList = List.of(new EdenMemoryPoolMXBean(), new SurvivorMemoryPoolMXBean(), new OldGenerationMemoryPoolMXBean()); + } else { + assert SubstrateOptions.UseEpsilonGC.getValue(); + beanList = List.of(new EpsilonMemoryPoolMXBean()); + } + mxBeans = beanList.toArray(AbstractMemoryPoolMXBean[]::new); + return beanList; + } + + public static void notifyAfterCollection() { + for (AbstractMemoryPoolMXBean bean: mxBeans) { + bean.afterCollection(); + } + } + + /** + * A MemoryPoolMXBean for the eden space. + */ + static final class EdenMemoryPoolMXBean extends AbstractMemoryPoolMXBean { + + @Platforms(Platform.HOSTED_ONLY.class) + public EdenMemoryPoolMXBean() { + super("eden space", "young generation scavenger", "complete scavenger"); + } + + @Override + void afterCollection() { + updatePeakUsage(GCImpl.getGCImpl().getAccounting().getEdenChunkBytesBefore()); + } + + @Override + public MemoryUsage getUsage() { + return memoryUsage(getCurrentUsage()); + } + + @Override + public MemoryUsage getPeakUsage() { + updatePeakUsage(getCurrentUsage()); + return memoryUsage(peakUsage.get()); + } + + @Override + public MemoryUsage getCollectionUsage() { + return memoryUsage(WordFactory.zero()); + } + + private static UnsignedWord getCurrentUsage() { + return HeapImpl.getHeapImpl().getAccounting().getEdenUsedBytes(); + } + + private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { + CollectionPolicy policy = GCImpl.getPolicy(); + UnsignedWord max = policy.getMaximumYoungGenerationSize().subtract(policy.getMaximumSurvivorSize()); + return new MemoryUsage(0L, usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), max.rawValue()); + } + } + + /** + * A MemoryPoolMXBean for the survivor spaces. + */ + static final class SurvivorMemoryPoolMXBean extends AbstractMemoryPoolMXBean { + + @Platforms(Platform.HOSTED_ONLY.class) + public SurvivorMemoryPoolMXBean() { + super("survivor space", "young generation scavenger", "complete scavenger"); + } + + @Override + void afterCollection() { + updatePeakUsage(GCImpl.getGCImpl().getAccounting().getYoungChunkBytesAfter()); + } + + @Override + public MemoryUsage getUsage() { + return getCollectionUsage(); + } + + @Override + public MemoryUsage getPeakUsage() { + return memoryUsage(peakUsage.get()); + } + + @Override + public MemoryUsage getCollectionUsage() { + return memoryUsage(GCImpl.getGCImpl().getAccounting().getYoungChunkBytesAfter()); + } + + private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { + UnsignedWord max = GCImpl.getPolicy().getMaximumSurvivorSize(); + return new MemoryUsage(0L, usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), max.rawValue()); + } + } + + /** + * A MemoryPoolMXBean for the old generation. + */ + static final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { + + @Platforms(Platform.HOSTED_ONLY.class) + public OldGenerationMemoryPoolMXBean() { + super("old generation space", "complete scavenger"); + } + + @Override + void afterCollection() { + updatePeakUsage(GCImpl.getGCImpl().getAccounting().getOldGenerationAfterChunkBytes()); + } + + @Override + public MemoryUsage getUsage() { + return getCollectionUsage(); + } + + @Override + public MemoryUsage getPeakUsage() { + return memoryUsage(peakUsage.get()); + } + + @Override + public MemoryUsage getCollectionUsage() { + return memoryUsage(GCImpl.getGCImpl().getAccounting().getOldGenerationAfterChunkBytes()); + } + + private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { + CollectionPolicy policy = GCImpl.getPolicy(); + UnsignedWord max = policy.getMaximumHeapSize().subtract(policy.getMaximumYoungGenerationSize()); + return new MemoryUsage(0L, usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), max.rawValue()); + } + } + + /** + * A MemoryPoolMXBean for the Epsilon collector. + */ + static final class EpsilonMemoryPoolMXBean extends AbstractMemoryPoolMXBean { + + private final long MAX_HEAP_SIZE = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); + + @Platforms(Platform.HOSTED_ONLY.class) + public EpsilonMemoryPoolMXBean() { + super("epsilon heap", "epsilon scavenger"); + } + + @Override + void afterCollection() { + } + + @Override + public MemoryUsage getUsage() { + HeapImpl heapImpl = HeapImpl.getHeapImpl(); + long used = heapImpl.getUsedBytes().rawValue(); + long committed = heapImpl.getCommittedBytes().rawValue(); + return memoryUsage(used, committed); + } + + @Override + public MemoryUsage getPeakUsage() { + return getUsage(); + } + + @Override + public MemoryUsage getCollectionUsage() { + return memoryUsage(0L, 0L); + } + + private MemoryUsage memoryUsage(long used, long committed) { + return new MemoryUsage(0L, used, committed, MAX_HEAP_SIZE); + } + } +} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java deleted file mode 100644 index f173f9456d3d..000000000000 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/OldGenerationMemoryPoolMXBean.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.genscavenge; - -import java.lang.management.MemoryUsage; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -/** - * A MemoryPoolMXBean for the old generation. - */ -public final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { - - @Platforms(Platform.HOSTED_ONLY.class) - public OldGenerationMemoryPoolMXBean() { - super("old generation space", "complete scavenger"); - } - - @Override - void beforeCollection() { - updatePeakUsage(gcAccounting.getOldChunkBytesBefore()); - } - - @Override - public MemoryUsage getUsage() { - long used = HeapImpl.getHeapImpl().getOldGeneration().getChunkBytes().rawValue(); - return memoryUsage(used); - } - - @Override - public MemoryUsage getPeakUsage() { - long peak = peakUsage.get().rawValue(); - return memoryUsage(peak); - } - - @Override - public MemoryUsage getCollectionUsage() { - long used = gcAccounting.getOldGenerationAfterChunkBytes().rawValue(); - return memoryUsage(used); - } - - private static MemoryUsage memoryUsage(long usedAndCommitted) { - CollectionPolicy policy = GCImpl.getPolicy(); - long maxHeap = policy.getMaximumHeapSize().rawValue(); - long maxYoung = policy.getMaximumYoungGenerationSize().rawValue(); - return new MemoryUsage(0L, usedAndCommitted, usedAndCommitted, maxHeap - maxYoung); - } -} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java deleted file mode 100644 index 3dc79ea62f6e..000000000000 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/YoungGenerationMemoryPoolMXBean.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.oracle.svm.core.genscavenge; - -import java.lang.management.MemoryUsage; - -import org.graalvm.nativeimage.Platform; -import org.graalvm.nativeimage.Platforms; - -/** - * A MemoryPoolMXBean for the young generation. - */ -public final class YoungGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { - - @Platforms(Platform.HOSTED_ONLY.class) - public YoungGenerationMemoryPoolMXBean() { - super("young generation space", "young generation scavenger", "complete scavenger"); - } - - @Override - void beforeCollection() { - updatePeakUsage(gcAccounting.getYoungChunkBytesBefore()); - } - - @Override - public MemoryUsage getUsage() { - return memoryUsage(getCurrentUsage()); - } - - @Override - public MemoryUsage getPeakUsage() { - long current = getCurrentUsage(); - long peak = peakUsage.get().rawValue(); - return memoryUsage(Math.max(current, peak)); - } - - @Override - public MemoryUsage getCollectionUsage() { - long used = gcAccounting.getYoungChunkBytesAfter().rawValue(); - return memoryUsage(used); - } - - private static long getCurrentUsage() { - return HeapImpl.getHeapImpl().getAccounting().getYoungUsedBytes().rawValue(); - } - - private static MemoryUsage memoryUsage(long usedAndCommitted) { - long max = GCImpl.getPolicy().getMaximumYoungGenerationSize().rawValue(); - return new MemoryUsage(0L, usedAndCommitted, usedAndCommitted, max); - } -} diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index 0a60ac9be223..ccd9c46f5dfc 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -28,8 +28,7 @@ import java.util.List; import java.util.Map; -import com.oracle.svm.core.genscavenge.OldGenerationMemoryPoolMXBean; -import com.oracle.svm.core.genscavenge.YoungGenerationMemoryPoolMXBean; +import com.oracle.svm.core.genscavenge.MemoryPoolMXBeans; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; @@ -94,7 +93,7 @@ public void duringSetup(DuringSetupAccess access) { ManagementSupport managementSupport = ManagementSupport.getSingleton(); managementSupport.addPlatformManagedObjectSingleton(java.lang.management.MemoryMXBean.class, new HeapImplMemoryMXBean()); - managementSupport.addPlatformManagedObjectList(java.lang.management.MemoryPoolMXBean.class, Arrays.asList(new YoungGenerationMemoryPoolMXBean(), new OldGenerationMemoryPoolMXBean())); + managementSupport.addPlatformManagedObjectList(java.lang.management.MemoryPoolMXBean.class, MemoryPoolMXBeans.createMemoryPoolMXBeans()); managementSupport.addPlatformManagedObjectList(com.sun.management.GarbageCollectorMXBean.class, Arrays.asList(new IncrementalGarbageCollectorMXBean(), new CompleteGarbageCollectorMXBean())); if (ImageSingletons.contains(PerfManager.class)) { From a73b1715d62da1036608f174a802d0227cd5bf87 Mon Sep 17 00:00:00 2001 From: peterz Date: Mon, 20 Feb 2023 18:59:59 +0300 Subject: [PATCH 09/14] Pass memory manager names as constructor parameters --- .../core/genscavenge/MemoryPoolMXBeans.java | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java index 1305e9e28a5b..8e4ef25bfc77 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java @@ -37,16 +37,23 @@ public class MemoryPoolMXBeans { + private static final String YOUNG_GEN_SCAVENGER = "young generation scavenger"; + private static final String COMPLETE_SCAVENGER = "complete scavenger"; + private static final String EPSILON_SCAVENGER = "epsilon scavenger"; + private static AbstractMemoryPoolMXBean[] mxBeans; @Platforms(Platform.HOSTED_ONLY.class) public static List createMemoryPoolMXBeans() { List beanList; if (SubstrateOptions.UseSerialGC.getValue()) { - beanList = List.of(new EdenMemoryPoolMXBean(), new SurvivorMemoryPoolMXBean(), new OldGenerationMemoryPoolMXBean()); + beanList = List.of( + new EdenMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), + new SurvivorMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), + new OldGenerationMemoryPoolMXBean(COMPLETE_SCAVENGER)); } else { assert SubstrateOptions.UseEpsilonGC.getValue(); - beanList = List.of(new EpsilonMemoryPoolMXBean()); + beanList = List.of(new EpsilonMemoryPoolMXBean(EPSILON_SCAVENGER)); } mxBeans = beanList.toArray(AbstractMemoryPoolMXBean[]::new); return beanList; @@ -64,8 +71,8 @@ public static void notifyAfterCollection() { static final class EdenMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public EdenMemoryPoolMXBean() { - super("eden space", "young generation scavenger", "complete scavenger"); + public EdenMemoryPoolMXBean(String... managerNames) { + super("eden space", managerNames); } @Override @@ -106,8 +113,8 @@ private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { static final class SurvivorMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public SurvivorMemoryPoolMXBean() { - super("survivor space", "young generation scavenger", "complete scavenger"); + public SurvivorMemoryPoolMXBean(String... managerNames) { + super("survivor space", managerNames); } @Override @@ -142,8 +149,8 @@ private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { static final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public OldGenerationMemoryPoolMXBean() { - super("old generation space", "complete scavenger"); + public OldGenerationMemoryPoolMXBean(String... managerNames) { + super("old generation space", managerNames); } @Override @@ -181,8 +188,8 @@ static final class EpsilonMemoryPoolMXBean extends AbstractMemoryPoolMXBean { private final long MAX_HEAP_SIZE = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); @Platforms(Platform.HOSTED_ONLY.class) - public EpsilonMemoryPoolMXBean() { - super("epsilon heap", "epsilon scavenger"); + public EpsilonMemoryPoolMXBean(String... managerNames) { + super("epsilon heap", managerNames); } @Override From cb8959f84504be72f4856849e77aa533eeb061c7 Mon Sep 17 00:00:00 2001 From: peterz Date: Tue, 21 Feb 2023 11:54:19 +0300 Subject: [PATCH 10/14] Added initial sizes --- .../genscavenge/AbstractMemoryPoolMXBean.java | 22 ++++++- .../core/genscavenge/MemoryPoolMXBeans.java | 61 ++++++++++++------- 2 files changed, 61 insertions(+), 22 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index 8b760774a165..87ea3b0dec0b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -29,6 +29,7 @@ import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; +import java.lang.management.MemoryUsage; import java.util.Arrays; import com.oracle.svm.core.heap.MXBeanBase; @@ -47,12 +48,31 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements Mem protected final String[] managerNames; protected final UninterruptibleUtils.AtomicUnsigned peakUsage = new UninterruptibleUtils.AtomicUnsigned(); + private static final UnsignedWord UNDEFINED = WordFactory.zero(); + protected UnsignedWord initialValue = UNDEFINED; + protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.name = name; this.managerNames = managerNames; } - abstract void afterCollection(); + UnsignedWord getInitialValue() { + if (initialValue.equal(UNDEFINED)) { + initialValue = computeInitialValue(); + } + return initialValue; + } + + abstract UnsignedWord computeInitialValue(); + + abstract UnsignedWord getMaximumValue(); + + MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { + return new MemoryUsage(getInitialValue().rawValue(), usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), getMaximumValue().rawValue()); + } + + void afterCollection() { + } @Override public String getName() { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java index 8e4ef25bfc77..943767a8959b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java @@ -75,6 +75,17 @@ public EdenMemoryPoolMXBean(String... managerNames) { super("eden space", managerNames); } + @Override + UnsignedWord computeInitialValue() { + return GCImpl.getPolicy() instanceof AbstractCollectionPolicy policy ? policy.sizes.initialEdenSize : WordFactory.signed(-1); + } + + @Override + UnsignedWord getMaximumValue() { + CollectionPolicy policy = GCImpl.getPolicy(); + return policy.getMaximumYoungGenerationSize().subtract(policy.getMaximumSurvivorSize()); + } + @Override void afterCollection() { updatePeakUsage(GCImpl.getGCImpl().getAccounting().getEdenChunkBytesBefore()); @@ -99,12 +110,6 @@ public MemoryUsage getCollectionUsage() { private static UnsignedWord getCurrentUsage() { return HeapImpl.getHeapImpl().getAccounting().getEdenUsedBytes(); } - - private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { - CollectionPolicy policy = GCImpl.getPolicy(); - UnsignedWord max = policy.getMaximumYoungGenerationSize().subtract(policy.getMaximumSurvivorSize()); - return new MemoryUsage(0L, usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), max.rawValue()); - } } /** @@ -117,6 +122,16 @@ public SurvivorMemoryPoolMXBean(String... managerNames) { super("survivor space", managerNames); } + @Override + UnsignedWord computeInitialValue() { + return GCImpl.getPolicy() instanceof AbstractCollectionPolicy policy ? policy.sizes.initialSurvivorSize : WordFactory.signed(-1); + } + + @Override + UnsignedWord getMaximumValue() { + return GCImpl.getPolicy().getMaximumSurvivorSize(); + } + @Override void afterCollection() { updatePeakUsage(GCImpl.getGCImpl().getAccounting().getYoungChunkBytesAfter()); @@ -136,11 +151,6 @@ public MemoryUsage getPeakUsage() { public MemoryUsage getCollectionUsage() { return memoryUsage(GCImpl.getGCImpl().getAccounting().getYoungChunkBytesAfter()); } - - private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { - UnsignedWord max = GCImpl.getPolicy().getMaximumSurvivorSize(); - return new MemoryUsage(0L, usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), max.rawValue()); - } } /** @@ -153,6 +163,17 @@ public OldGenerationMemoryPoolMXBean(String... managerNames) { super("old generation space", managerNames); } + @Override + UnsignedWord computeInitialValue() { + return GCImpl.getPolicy() instanceof AbstractCollectionPolicy policy ? policy.sizes.initialOldSize() : WordFactory.signed(-1); + } + + @Override + UnsignedWord getMaximumValue() { + CollectionPolicy policy = GCImpl.getPolicy(); + return policy.getMaximumHeapSize().subtract(policy.getMaximumYoungGenerationSize()); + } + @Override void afterCollection() { updatePeakUsage(GCImpl.getGCImpl().getAccounting().getOldGenerationAfterChunkBytes()); @@ -172,12 +193,6 @@ public MemoryUsage getPeakUsage() { public MemoryUsage getCollectionUsage() { return memoryUsage(GCImpl.getGCImpl().getAccounting().getOldGenerationAfterChunkBytes()); } - - private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { - CollectionPolicy policy = GCImpl.getPolicy(); - UnsignedWord max = policy.getMaximumHeapSize().subtract(policy.getMaximumYoungGenerationSize()); - return new MemoryUsage(0L, usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), max.rawValue()); - } } /** @@ -185,15 +200,19 @@ private static MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { */ static final class EpsilonMemoryPoolMXBean extends AbstractMemoryPoolMXBean { - private final long MAX_HEAP_SIZE = GCImpl.getPolicy().getMaximumHeapSize().rawValue(); - @Platforms(Platform.HOSTED_ONLY.class) public EpsilonMemoryPoolMXBean(String... managerNames) { super("epsilon heap", managerNames); } @Override - void afterCollection() { + UnsignedWord computeInitialValue() { + return GCImpl.getPolicy().getMinimumHeapSize(); + } + + @Override + UnsignedWord getMaximumValue() { + return GCImpl.getPolicy().getMaximumHeapSize(); } @Override @@ -215,7 +234,7 @@ public MemoryUsage getCollectionUsage() { } private MemoryUsage memoryUsage(long used, long committed) { - return new MemoryUsage(0L, used, committed, MAX_HEAP_SIZE); + return new MemoryUsage(getInitialValue().rawValue(), used, committed, getMaximumValue().rawValue()); } } } From c646b2da7ccdffd672a7ad4a23b23ecba6235888 Mon Sep 17 00:00:00 2001 From: peterz Date: Tue, 21 Feb 2023 12:08:30 +0300 Subject: [PATCH 11/14] Copyrights and checkstyle --- .../core/genscavenge/AbstractMemoryPoolMXBean.java | 6 +++--- .../svm/core/genscavenge/MemoryPoolMXBeans.java | 12 ++++++------ .../src/com/oracle/svm/core/heap/MXBeanBase.java | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index 87ea3b0dec0b..e308fd2b1fb6 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2023, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,6 @@ import org.graalvm.word.WordFactory; import sun.management.Util; -@Platforms(Platform.HOSTED_ONLY.class) public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements MemoryPoolMXBean { protected final String name; @@ -51,6 +50,7 @@ public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements Mem private static final UnsignedWord UNDEFINED = WordFactory.zero(); protected UnsignedWord initialValue = UNDEFINED; + @Platforms(Platform.HOSTED_ONLY.class) protected AbstractMemoryPoolMXBean(String name, String... managerNames) { this.name = name; this.managerNames = managerNames; diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java index 943767a8959b..4f01f3c5eb7e 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2023, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ public static void notifyAfterCollection() { static final class EdenMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public EdenMemoryPoolMXBean(String... managerNames) { + EdenMemoryPoolMXBean(String... managerNames) { super("eden space", managerNames); } @@ -118,7 +118,7 @@ private static UnsignedWord getCurrentUsage() { static final class SurvivorMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public SurvivorMemoryPoolMXBean(String... managerNames) { + SurvivorMemoryPoolMXBean(String... managerNames) { super("survivor space", managerNames); } @@ -159,7 +159,7 @@ public MemoryUsage getCollectionUsage() { static final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public OldGenerationMemoryPoolMXBean(String... managerNames) { + OldGenerationMemoryPoolMXBean(String... managerNames) { super("old generation space", managerNames); } @@ -201,7 +201,7 @@ public MemoryUsage getCollectionUsage() { static final class EpsilonMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) - public EpsilonMemoryPoolMXBean(String... managerNames) { + EpsilonMemoryPoolMXBean(String... managerNames) { super("epsilon heap", managerNames); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java index 6eef37003ee8..e02aacb2228c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2022, 2022, BELLSOFT. All rights reserved. + * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2023, BELLSOFT. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it From f41ef2ae02ed99bfc66c8afe2d0f2701a8e59c47 Mon Sep 17 00:00:00 2001 From: peterz Date: Wed, 22 Feb 2023 15:42:30 +0300 Subject: [PATCH 12/14] Style fixes --- .../src/com/oracle/svm/core/genscavenge/GCAccounting.java | 4 ++-- .../oracle/svm/core/genscavenge/MemoryPoolMXBeans.java | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index c2a658511314..4a2ec1fee29f 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -147,8 +147,8 @@ void beforeCollection(boolean completeCollection) { lastIncrementalCollectionOverflowedSurvivors = false; } trace.string(" edenChunkBytesBefore: ").unsigned(edenChunkBytesBefore) - .string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) - .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); + .string(" youngChunkBytesBefore: ").unsigned(youngChunkBytesBefore) + .string(" oldChunkBytesBefore: ").unsigned(oldChunkBytesBefore); trace.string("]").newline(); } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java index 4f01f3c5eb7e..5e45ae97de30 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java @@ -48,9 +48,9 @@ public static List createMemoryPoolMXBeans() { List beanList; if (SubstrateOptions.UseSerialGC.getValue()) { beanList = List.of( - new EdenMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), - new SurvivorMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), - new OldGenerationMemoryPoolMXBean(COMPLETE_SCAVENGER)); + new EdenMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), + new SurvivorMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), + new OldGenerationMemoryPoolMXBean(COMPLETE_SCAVENGER)); } else { assert SubstrateOptions.UseEpsilonGC.getValue(); beanList = List.of(new EpsilonMemoryPoolMXBean(EPSILON_SCAVENGER)); @@ -60,7 +60,7 @@ public static List createMemoryPoolMXBeans() { } public static void notifyAfterCollection() { - for (AbstractMemoryPoolMXBean bean: mxBeans) { + for (AbstractMemoryPoolMXBean bean : mxBeans) { bean.afterCollection(); } } From 4d1b8fb1ec4b7643d9beb68ea637c691f5310592 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Wed, 22 Feb 2023 19:01:47 +0100 Subject: [PATCH 13/14] Cleanups and fixes. --- substratevm/CHANGELOG.md | 1 + .../genscavenge/AbstractCollectionPolicy.java | 32 ++++++- .../genscavenge/AbstractMemoryPoolMXBean.java | 28 ++++--- .../genscavenge/AdaptiveCollectionPolicy.java | 2 +- .../genscavenge/BasicCollectionPolicies.java | 25 ++++++ .../core/genscavenge/CollectionPolicy.java | 17 +++- .../svm/core/genscavenge/GCAccounting.java | 1 - .../oracle/svm/core/genscavenge/GCImpl.java | 10 ++- ...java => GenScavengeMemoryPoolMXBeans.java} | 83 ++++++++----------- .../graal/GenScavengeGCFeature.java | 7 +- .../{MXBeanBase.java => AbstractMXBean.java} | 2 +- .../svm/core/heap/AbstractMemoryMXBean.java | 2 +- .../jdk/management/ManagementSupport.java | 6 -- 13 files changed, 138 insertions(+), 78 deletions(-) rename substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/{MemoryPoolMXBeans.java => GenScavengeMemoryPoolMXBeans.java} (72%) rename substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/{MXBeanBase.java => AbstractMXBean.java} (96%) diff --git a/substratevm/CHANGELOG.md b/substratevm/CHANGELOG.md index 515d8dc22998..9a54d9c816f9 100644 --- a/substratevm/CHANGELOG.md +++ b/substratevm/CHANGELOG.md @@ -22,6 +22,7 @@ This changelog summarizes major changes to GraalVM Native Image. * (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`. * (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. * (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). +* (GR-38414) BellSoft implemented the `MemoryPoolMXBean` for the serial and epsilon GCs. ## Version 22.3.0 * (GR-35721) Remove old build output style and the `-H:±BuildOutputUseNewStyle` option. diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java index d4b72acf7967..f5f8a4e14b4d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractCollectionPolicy.java @@ -26,7 +26,6 @@ import java.util.concurrent.atomic.AtomicBoolean; -import com.oracle.svm.core.heap.GCCause; import org.graalvm.compiler.api.replacements.Fold; import org.graalvm.compiler.nodes.PauseNode; import org.graalvm.nativeimage.Platform; @@ -36,6 +35,7 @@ import com.oracle.svm.core.SubstrateGCOptions; import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.heap.GCCause; import com.oracle.svm.core.heap.PhysicalMemory; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.jdk.UninterruptibleUtils; @@ -193,13 +193,21 @@ private void updateSizeParametersLocked(SizeParameters params, SizeParameters pr * but we must still ensure that computations can handle it (for example, no overflows). */ survivorSize = UnsignedUtils.min(survivorSize, params.maxSurvivorSize()); - edenSize = UnsignedUtils.min(edenSize, maxEdenSize()); + edenSize = UnsignedUtils.min(edenSize, getMaximumEdenSize()); oldSize = UnsignedUtils.min(oldSize, params.maxOldSize()); promoSize = UnsignedUtils.min(promoSize, params.maxOldSize()); } + @Override + public UnsignedWord getInitialEdenSize() { + guaranteeSizeParametersInitialized(); + return sizes.initialEdenSize; + } + + @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - protected UnsignedWord maxEdenSize() { + public UnsignedWord getMaximumEdenSize() { + guaranteeSizeParametersInitialized(); return alignDown(sizes.maxYoungSize.subtract(survivorSize.multiply(2))); } @@ -215,6 +223,12 @@ public UnsignedWord getMaximumYoungGenerationSize() { return sizes.maxYoungSize; } + @Override + public UnsignedWord getInitialSurvivorSize() { + guaranteeSizeParametersInitialized(); + return sizes.initialSurvivorSize; + } + @Override public UnsignedWord getMaximumSurvivorSize() { guaranteeSizeParametersInitialized(); @@ -242,6 +256,18 @@ public UnsignedWord getYoungGenerationCapacity() { return edenSize.add(survivorSize); } + @Override + public UnsignedWord getInitialOldSize() { + guaranteeSizeParametersInitialized(); + return sizes.initialOldSize(); + } + + @Override + public UnsignedWord getMaximumOldSize() { + guaranteeSizeParametersInitialized(); + return sizes.maxOldSize(); + } + @Override public UnsignedWord getOldGenerationCapacity() { guaranteeSizeParametersInitialized(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java index e308fd2b1fb6..f2a23be29ba3 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AbstractMemoryPoolMXBean.java @@ -25,26 +25,28 @@ */ package com.oracle.svm.core.genscavenge; -import javax.management.ObjectName; import java.lang.management.ManagementFactory; import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryType; import java.lang.management.MemoryUsage; import java.util.Arrays; -import com.oracle.svm.core.heap.MXBeanBase; -import com.oracle.svm.core.jdk.UninterruptibleUtils; -import com.oracle.svm.core.util.UnsignedUtils; +import javax.management.ObjectName; + import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; + +import com.oracle.svm.core.heap.AbstractMXBean; +import com.oracle.svm.core.jdk.UninterruptibleUtils; + import sun.management.Util; -public abstract class AbstractMemoryPoolMXBean extends MXBeanBase implements MemoryPoolMXBean { +public abstract class AbstractMemoryPoolMXBean extends AbstractMXBean implements MemoryPoolMXBean { - protected final String name; - protected final String[] managerNames; + private final String name; + private final String[] managerNames; protected final UninterruptibleUtils.AtomicUnsigned peakUsage = new UninterruptibleUtils.AtomicUnsigned(); private static final UnsignedWord UNDEFINED = WordFactory.zero(); @@ -67,11 +69,14 @@ UnsignedWord getInitialValue() { abstract UnsignedWord getMaximumValue(); + abstract void afterCollection(GCAccounting accounting); + MemoryUsage memoryUsage(UnsignedWord usedAndCommitted) { return new MemoryUsage(getInitialValue().rawValue(), usedAndCommitted.rawValue(), usedAndCommitted.rawValue(), getMaximumValue().rawValue()); } - void afterCollection() { + MemoryUsage memoryUsage(UnsignedWord used, UnsignedWord committed) { + return new MemoryUsage(getInitialValue().rawValue(), used.rawValue(), committed.rawValue(), getMaximumValue().rawValue()); } @Override @@ -154,7 +159,10 @@ public void resetPeakUsage() { peakUsage.set(WordFactory.zero()); } - void updatePeakUsage(UnsignedWord currentValue) { - peakUsage.set(UnsignedUtils.max(peakUsage.get(), currentValue)); + void updatePeakUsage(UnsignedWord value) { + UnsignedWord current; + do { + current = peakUsage.get(); + } while (value.aboveThan(current) && !peakUsage.compareAndSet(current, value)); } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java index fe3c3e78b945..9175c859012b 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/AdaptiveCollectionPolicy.java @@ -270,7 +270,7 @@ protected void computeEdenSpaceSize(@SuppressWarnings("unused") boolean complete assert isAligned(desiredEdenSize); desiredEdenSize = minSpaceSize(desiredEdenSize); - UnsignedWord edenLimit = maxEdenSize(); + UnsignedWord edenLimit = getMaximumEdenSize(); if (desiredEdenSize.aboveThan(edenLimit)) { /* * If the policy says to get a larger eden but is hitting the limit, don't decrease diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java index 3376a06831bb..ae89d3740679 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/BasicCollectionPolicies.java @@ -87,6 +87,16 @@ public void updateSizeParameters() { // Size parameters are recomputed from current values whenever they are queried } + @Override + public UnsignedWord getInitialEdenSize() { + return UNDEFINED; + } + + @Override + public UnsignedWord getMaximumEdenSize() { + return getMaximumYoungGenerationSize(); + } + @Override public final UnsignedWord getMaximumHeapSize() { long runtimeValue = SubstrateGCOptions.MaxHeapSize.getValue(); @@ -146,6 +156,11 @@ public final UnsignedWord getMinimumHeapSize() { return result; } + @Override + public UnsignedWord getInitialSurvivorSize() { + return UNDEFINED; + } + @Override public UnsignedWord getMaximumSurvivorSize() { return WordFactory.zero(); @@ -161,6 +176,11 @@ public UnsignedWord getYoungGenerationCapacity() { return getMaximumYoungGenerationSize(); } + @Override + public UnsignedWord getInitialOldSize() { + return UNDEFINED; + } + @Override public UnsignedWord getOldGenerationCapacity() { UnsignedWord heapCapacity = getCurrentHeapCapacity(); @@ -171,6 +191,11 @@ public UnsignedWord getOldGenerationCapacity() { return heapCapacity.subtract(youngCapacity); } + @Override + public UnsignedWord getMaximumOldSize() { + return getOldGenerationCapacity(); + } + @Override public final UnsignedWord getMaximumFreeAlignedChunksSize() { return getMaximumYoungGenerationSize(); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java index 129f3a639e75..1d11025ef0f7 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/CollectionPolicy.java @@ -27,6 +27,7 @@ import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.UnsignedWord; +import org.graalvm.word.WordFactory; import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.heap.GCCause; @@ -36,6 +37,8 @@ /** The interface for a garbage collection policy. All sizes are in bytes. */ public interface CollectionPolicy { + UnsignedWord UNDEFINED = WordFactory.unsigned(-1); + @Platforms(Platform.HOSTED_ONLY.class) static String getInitialPolicyName() { if (SubstrateOptions.UseEpsilonGC.getValue()) { @@ -143,6 +146,11 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) { */ UnsignedWord getCurrentHeapCapacity(); + /** May be {@link #UNDEFINED}. */ + UnsignedWord getInitialEdenSize(); + + UnsignedWord getMaximumEdenSize(); + /** * The hard limit for the size of the entire heap. Exceeding this limit triggers an * {@link OutOfMemoryError}. @@ -158,6 +166,9 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) { /** The minimum heap size, for inclusion in diagnostic output. */ UnsignedWord getMinimumHeapSize(); + /** May be {@link #UNDEFINED}. */ + UnsignedWord getInitialSurvivorSize(); + UnsignedWord getMaximumSurvivorSize(); /** @@ -170,9 +181,14 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) { /** The capacity of the young generation, comprising the eden and survivor spaces. */ UnsignedWord getYoungGenerationCapacity(); + /** May be {@link #UNDEFINED}. */ + UnsignedWord getInitialOldSize(); + /** The capacity of the old generation. */ UnsignedWord getOldGenerationCapacity(); + UnsignedWord getMaximumOldSize(); + /** * The maximum number of bytes that should be kept readily available for allocation or copying * during collections. @@ -191,5 +207,4 @@ static boolean shouldCollectYoungGenSeparately(boolean defaultValue) { /** Called before the end of a collection, in the safepoint operation. */ void onCollectionEnd(boolean completeCollection, GCCause cause); - } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java index 4a2ec1fee29f..128df06b6087 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCAccounting.java @@ -164,7 +164,6 @@ void afterCollection(boolean completeCollection, Timer collectionTimer) { } else { afterIncrementalCollection(collectionTimer); } - MemoryPoolMXBeans.notifyAfterCollection(); } private void afterIncrementalCollection(Timer collectionTimer) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java index 58bb66d00afc..38d58ce2587d 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GCImpl.java @@ -43,15 +43,14 @@ import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; +import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.MemoryWalker; +import com.oracle.svm.core.NeverInline; import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.SubstrateGCOptions; import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.UnmanagedMemoryUtil; -import com.oracle.svm.core.AlwaysInline; -import com.oracle.svm.core.NeverInline; -import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.UnmanagedMemoryUtil; import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoAccess; @@ -74,6 +73,7 @@ import com.oracle.svm.core.heap.OutOfMemoryUtil; import com.oracle.svm.core.heap.ReferenceHandler; import com.oracle.svm.core.heap.ReferenceMapIndex; +import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.heap.RuntimeCodeCacheCleaner; import com.oracle.svm.core.heap.VMOperationInfos; import com.oracle.svm.core.jdk.RuntimeSupport; @@ -294,6 +294,8 @@ private boolean doCollectOnce(GCCause cause, long requestingNanoTime, boolean co accounting.afterCollection(completeCollection, collectionTimer); policy.onCollectionEnd(completeCollection, cause); + GenScavengeMemoryPoolMXBeans.notifyAfterCollection(accounting); + UnsignedWord usedBytes = getChunkBytes(); UnsignedWord freeBytes = policy.getCurrentHeapCapacity().subtract(usedBytes); ReferenceObjectProcessing.afterCollection(freeBytes); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeMemoryPoolMXBeans.java similarity index 72% rename from substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java rename to substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeMemoryPoolMXBeans.java index 5e45ae97de30..4e0daf2c7dc0 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/MemoryPoolMXBeans.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/GenScavengeMemoryPoolMXBeans.java @@ -25,17 +25,18 @@ */ package com.oracle.svm.core.genscavenge; -import com.oracle.svm.core.SubstrateOptions; +import java.lang.management.MemoryPoolMXBean; +import java.lang.management.MemoryUsage; + import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; -import java.lang.management.MemoryPoolMXBean; -import java.lang.management.MemoryUsage; -import java.util.List; +import com.oracle.svm.core.SubstrateOptions; +import com.oracle.svm.core.util.VMError; -public class MemoryPoolMXBeans { +public class GenScavengeMemoryPoolMXBeans { private static final String YOUNG_GEN_SCAVENGER = "young generation scavenger"; private static final String COMPLETE_SCAVENGER = "complete scavenger"; @@ -44,30 +45,28 @@ public class MemoryPoolMXBeans { private static AbstractMemoryPoolMXBean[] mxBeans; @Platforms(Platform.HOSTED_ONLY.class) - public static List createMemoryPoolMXBeans() { - List beanList; + public static MemoryPoolMXBean[] createMemoryPoolMXBeans() { if (SubstrateOptions.UseSerialGC.getValue()) { - beanList = List.of( + mxBeans = new AbstractMemoryPoolMXBean[]{ new EdenMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), new SurvivorMemoryPoolMXBean(YOUNG_GEN_SCAVENGER, COMPLETE_SCAVENGER), - new OldGenerationMemoryPoolMXBean(COMPLETE_SCAVENGER)); + new OldGenerationMemoryPoolMXBean(COMPLETE_SCAVENGER) + }; } else { assert SubstrateOptions.UseEpsilonGC.getValue(); - beanList = List.of(new EpsilonMemoryPoolMXBean(EPSILON_SCAVENGER)); + mxBeans = new AbstractMemoryPoolMXBean[]{ + new EpsilonMemoryPoolMXBean(EPSILON_SCAVENGER) + }; } - mxBeans = beanList.toArray(AbstractMemoryPoolMXBean[]::new); - return beanList; + return mxBeans; } - public static void notifyAfterCollection() { - for (AbstractMemoryPoolMXBean bean : mxBeans) { - bean.afterCollection(); + public static void notifyAfterCollection(GCAccounting accounting) { + for (AbstractMemoryPoolMXBean mxBean : mxBeans) { + mxBean.afterCollection(accounting); } } - /** - * A MemoryPoolMXBean for the eden space. - */ static final class EdenMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) @@ -77,18 +76,17 @@ static final class EdenMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Override UnsignedWord computeInitialValue() { - return GCImpl.getPolicy() instanceof AbstractCollectionPolicy policy ? policy.sizes.initialEdenSize : WordFactory.signed(-1); + return GCImpl.getPolicy().getInitialEdenSize(); } @Override UnsignedWord getMaximumValue() { - CollectionPolicy policy = GCImpl.getPolicy(); - return policy.getMaximumYoungGenerationSize().subtract(policy.getMaximumSurvivorSize()); + return GCImpl.getPolicy().getMaximumEdenSize(); } @Override - void afterCollection() { - updatePeakUsage(GCImpl.getGCImpl().getAccounting().getEdenChunkBytesBefore()); + void afterCollection(GCAccounting accounting) { + updatePeakUsage(accounting.getEdenChunkBytesBefore()); } @Override @@ -112,9 +110,6 @@ private static UnsignedWord getCurrentUsage() { } } - /** - * A MemoryPoolMXBean for the survivor spaces. - */ static final class SurvivorMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) @@ -124,7 +119,7 @@ static final class SurvivorMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Override UnsignedWord computeInitialValue() { - return GCImpl.getPolicy() instanceof AbstractCollectionPolicy policy ? policy.sizes.initialSurvivorSize : WordFactory.signed(-1); + return GCImpl.getPolicy().getInitialSurvivorSize(); } @Override @@ -133,8 +128,8 @@ UnsignedWord getMaximumValue() { } @Override - void afterCollection() { - updatePeakUsage(GCImpl.getGCImpl().getAccounting().getYoungChunkBytesAfter()); + void afterCollection(GCAccounting accounting) { + updatePeakUsage(accounting.getYoungChunkBytesAfter()); } @Override @@ -153,9 +148,6 @@ public MemoryUsage getCollectionUsage() { } } - /** - * A MemoryPoolMXBean for the old generation. - */ static final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) @@ -165,18 +157,17 @@ static final class OldGenerationMemoryPoolMXBean extends AbstractMemoryPoolMXBea @Override UnsignedWord computeInitialValue() { - return GCImpl.getPolicy() instanceof AbstractCollectionPolicy policy ? policy.sizes.initialOldSize() : WordFactory.signed(-1); + return GCImpl.getPolicy().getInitialOldSize(); } @Override UnsignedWord getMaximumValue() { - CollectionPolicy policy = GCImpl.getPolicy(); - return policy.getMaximumHeapSize().subtract(policy.getMaximumYoungGenerationSize()); + return GCImpl.getPolicy().getMaximumOldSize(); } @Override - void afterCollection() { - updatePeakUsage(GCImpl.getGCImpl().getAccounting().getOldGenerationAfterChunkBytes()); + void afterCollection(GCAccounting accounting) { + updatePeakUsage(accounting.getOldGenerationAfterChunkBytes()); } @Override @@ -195,9 +186,6 @@ public MemoryUsage getCollectionUsage() { } } - /** - * A MemoryPoolMXBean for the Epsilon collector. - */ static final class EpsilonMemoryPoolMXBean extends AbstractMemoryPoolMXBean { @Platforms(Platform.HOSTED_ONLY.class) @@ -215,12 +203,15 @@ UnsignedWord getMaximumValue() { return GCImpl.getPolicy().getMaximumHeapSize(); } + @Override + void afterCollection(GCAccounting accounting) { + throw VMError.shouldNotReachHere(); + } + @Override public MemoryUsage getUsage() { HeapImpl heapImpl = HeapImpl.getHeapImpl(); - long used = heapImpl.getUsedBytes().rawValue(); - long committed = heapImpl.getCommittedBytes().rawValue(); - return memoryUsage(used, committed); + return memoryUsage(heapImpl.getUsedBytes(), heapImpl.getCommittedBytes()); } @Override @@ -230,11 +221,7 @@ public MemoryUsage getPeakUsage() { @Override public MemoryUsage getCollectionUsage() { - return memoryUsage(0L, 0L); - } - - private MemoryUsage memoryUsage(long used, long committed) { - return new MemoryUsage(getInitialValue().rawValue(), used, committed, getMaximumValue().rawValue()); + return memoryUsage(WordFactory.zero()); } } } diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java index ccd9c46f5dfc..8216f42ead84 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeGCFeature.java @@ -25,10 +25,10 @@ package com.oracle.svm.core.genscavenge.graal; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Map; -import com.oracle.svm.core.genscavenge.MemoryPoolMXBeans; import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; @@ -40,6 +40,7 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.genscavenge.ChunkedImageHeapLayouter; import com.oracle.svm.core.genscavenge.CompleteGarbageCollectorMXBean; +import com.oracle.svm.core.genscavenge.GenScavengeMemoryPoolMXBeans; import com.oracle.svm.core.genscavenge.HeapImpl; import com.oracle.svm.core.genscavenge.HeapImplMemoryMXBean; import com.oracle.svm.core.genscavenge.ImageHeapInfo; @@ -93,8 +94,10 @@ public void duringSetup(DuringSetupAccess access) { ManagementSupport managementSupport = ManagementSupport.getSingleton(); managementSupport.addPlatformManagedObjectSingleton(java.lang.management.MemoryMXBean.class, new HeapImplMemoryMXBean()); - managementSupport.addPlatformManagedObjectList(java.lang.management.MemoryPoolMXBean.class, MemoryPoolMXBeans.createMemoryPoolMXBeans()); + managementSupport.addPlatformManagedObjectList(java.lang.management.MemoryPoolMXBean.class, Arrays.asList(GenScavengeMemoryPoolMXBeans.createMemoryPoolMXBeans())); managementSupport.addPlatformManagedObjectList(com.sun.management.GarbageCollectorMXBean.class, Arrays.asList(new IncrementalGarbageCollectorMXBean(), new CompleteGarbageCollectorMXBean())); + /* Not supported yet. */ + managementSupport.addPlatformManagedObjectList(java.lang.management.BufferPoolMXBean.class, Collections.emptyList()); if (ImageSingletons.contains(PerfManager.class)) { ImageSingletons.lookup(PerfManager.class).register(createPerfData()); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMXBean.java similarity index 96% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMXBean.java index e02aacb2228c..c9e2a269cc98 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/MXBeanBase.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMXBean.java @@ -30,7 +30,7 @@ import javax.management.NotificationFilter; import javax.management.NotificationListener; -public class MXBeanBase implements NotificationEmitter { +public abstract class AbstractMXBean implements NotificationEmitter { protected static final long UNDEFINED_MEMORY_USAGE = -1L; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java index 99c416002cd6..f067c5c3ecc7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/AbstractMemoryMXBean.java @@ -44,7 +44,7 @@ import sun.management.Util; -public abstract class AbstractMemoryMXBean extends MXBeanBase implements MemoryMXBean { +public abstract class AbstractMemoryMXBean extends AbstractMXBean implements MemoryMXBean { private final MemoryMXBeanCodeInfoVisitor codeInfoVisitor; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java index e969b1036e31..ca96c3bc827e 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/management/ManagementSupport.java @@ -141,12 +141,6 @@ public final class ManagementSupport implements ThreadListener { addPlatformManagedObjectSingleton(java.lang.management.CompilationMXBean.class, compilationMXBean); addPlatformManagedObjectSingleton(java.lang.management.RuntimeMXBean.class, runtimeMXBean); addPlatformManagedObjectSingleton(com.sun.management.ThreadMXBean.class, threadMXBean); - /* - * The following platform objects must be registered as existing and valid, even though we - * do not have an implementation yet. - */ - addPlatformManagedObjectList(java.lang.management.MemoryPoolMXBean.class, Collections.emptyList()); - addPlatformManagedObjectList(java.lang.management.BufferPoolMXBean.class, Collections.emptyList()); /* * Register the platform object for the OS using a supplier that lazily initializes it at * run time. From cdb05d456741f932147689c1cc3a549192472be2 Mon Sep 17 00:00:00 2001 From: Christian Haeubl Date: Thu, 23 Feb 2023 08:59:42 +0100 Subject: [PATCH 14/14] JFR-related bugfix. --- .../src/com/oracle/svm/core/jfr/JfrJavaEvents.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrJavaEvents.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrJavaEvents.java index d62c88d9468e..b7be9929e6e1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrJavaEvents.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/JfrJavaEvents.java @@ -39,7 +39,7 @@ public class JfrJavaEvents { @Platforms(Platform.HOSTED_ONLY.class) @SuppressWarnings("unchecked") - public static void registerEventClass(Class eventClass) { + public static synchronized void registerEventClass(Class eventClass) { EVENT_CLASSES.add(eventClass); if (jdk.jfr.Event.class.isAssignableFrom(eventClass)) { JFR_EVENT_CLASSES.add((Class) eventClass);