Skip to content

Commit 60a62b5

Browse files
simplified virtual memory tracking
1 parent a555374 commit 60a62b5

File tree

9 files changed

+406
-77
lines changed

9 files changed

+406
-77
lines changed

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

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.oracle.svm.core.genscavenge;
2626

27+
import com.oracle.svm.core.VMInspectionOptions;
2728
import org.graalvm.nativeimage.Platform;
2829
import org.graalvm.nativeimage.Platforms;
2930
import org.graalvm.word.Pointer;
@@ -40,6 +41,8 @@
4041
import com.oracle.svm.core.jdk.UninterruptibleUtils;
4142
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicUnsigned;
4243
import com.oracle.svm.core.log.Log;
44+
import com.oracle.svm.core.nmt.NmtCategory;
45+
import com.oracle.svm.core.nmt.NativeMemoryTracking;
4346
import com.oracle.svm.core.os.ChunkBasedCommittedMemoryProvider;
4447
import com.oracle.svm.core.thread.VMOperation;
4548
import com.oracle.svm.core.thread.VMThreads;
@@ -93,7 +96,10 @@ AlignedHeader produceAlignedChunk() {
9396
if (result.isNull()) {
9497
throw OutOfMemoryUtil.reportOutOfMemoryError(ALIGNED_OUT_OF_MEMORY_ERROR);
9598
}
96-
99+
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
100+
NativeMemoryTracking.singleton().trackReserve(chunkSize.rawValue(), NmtCategory.JavaHeap);
101+
NativeMemoryTracking.singleton().trackCommit(chunkSize.rawValue(), NmtCategory.JavaHeap);
102+
}
97103
AlignedHeapChunk.initialize(result, chunkSize);
98104
}
99105
assert HeapChunk.getTopOffset(result).equal(AlignedHeapChunk.getObjectsStartOffset());
@@ -244,7 +250,10 @@ UnalignedHeader produceUnalignedChunk(UnsignedWord objectSize) {
244250
if (result.isNull()) {
245251
throw OutOfMemoryUtil.reportOutOfMemoryError(UNALIGNED_OUT_OF_MEMORY_ERROR);
246252
}
247-
253+
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
254+
NativeMemoryTracking.singleton().trackReserve(chunkSize.rawValue(), NmtCategory.JavaHeap);
255+
NativeMemoryTracking.singleton().trackCommit(chunkSize.rawValue(), NmtCategory.JavaHeap);
256+
}
248257
UnalignedHeapChunk.initialize(result, chunkSize);
249258
assert objectSize.belowOrEqual(HeapChunk.availableObjectMemory(result)) : "UnalignedHeapChunk insufficient for requested object";
250259

@@ -306,12 +315,22 @@ static void freeUnalignedChunkList(UnalignedHeader first) {
306315

307316
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
308317
private static void freeAlignedChunk(AlignedHeader chunk) {
309-
ChunkBasedCommittedMemoryProvider.get().freeAlignedChunk(chunk, HeapParameters.getAlignedHeapChunkSize(), HeapParameters.getAlignedHeapChunkAlignment());
318+
UnsignedWord size = HeapParameters.getAlignedHeapChunkSize();
319+
ChunkBasedCommittedMemoryProvider.get().freeAlignedChunk(chunk, size, HeapParameters.getAlignedHeapChunkAlignment());
320+
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
321+
NativeMemoryTracking.singleton().trackUncommit(size.rawValue(), NmtCategory.JavaHeap);
322+
NativeMemoryTracking.singleton().trackFree(size.rawValue(), NmtCategory.JavaHeap);
323+
}
310324
}
311325

312326
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
313327
private static void freeUnalignedChunk(UnalignedHeader chunk) {
314-
ChunkBasedCommittedMemoryProvider.get().freeUnalignedChunk(chunk, unalignedChunkSize(chunk));
328+
UnsignedWord size = unalignedChunkSize(chunk);
329+
ChunkBasedCommittedMemoryProvider.get().freeUnalignedChunk(chunk, size);
330+
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
331+
NativeMemoryTracking.singleton().trackUncommit(size.rawValue(), NmtCategory.JavaHeap);
332+
NativeMemoryTracking.singleton().trackFree(size.rawValue(), NmtCategory.JavaHeap);
333+
}
315334
}
316335

317336
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)

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

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ public final class HeapImpl extends Heap {
115115
/** Total number of times when threads waiting for a pending reference list were interrupted. */
116116
private volatile long refListWaiterWakeUpCounter;
117117

118+
private volatile long imageHeapSize = -1;
119+
118120
/** Head of the linked list of object pins. */
119121
private final AtomicReference<PinnedObjectImpl> pinHead = new AtomicReference<>();
120122

@@ -475,6 +477,36 @@ public boolean walkImageHeapObjects(ObjectVisitor visitor) {
475477
return !AuxiliaryImageHeap.isPresent() || AuxiliaryImageHeap.singleton().walkObjects(visitor);
476478
}
477479

480+
@Override
481+
public long getImageHeapSize() {
482+
ImageHeapSizeVisitor visitor = new ImageHeapSizeVisitor();
483+
if (imageHeapSize == -1) {
484+
for (ImageHeapInfo info = firstImageHeapInfo; info != null; info = info.next) {
485+
ImageHeapWalker.walkRegions(info, visitor);
486+
}
487+
imageHeapSize = visitor.size;
488+
}
489+
return imageHeapSize;
490+
}
491+
492+
private static class ImageHeapSizeVisitor implements MemoryWalker.ImageHeapRegionVisitor, ObjectVisitor {
493+
long size;
494+
495+
@Override
496+
public <T> boolean visitNativeImageHeapRegion(T region, MemoryWalker.NativeImageHeapRegionAccess<T> access) {
497+
if (!access.isWritable(region) && !access.consistsOfHugeObjects(region)) {
498+
size += access.getSize(region).rawValue();
499+
}
500+
return true;
501+
}
502+
503+
@Override
504+
@RestrictHeapAccess(access = RestrictHeapAccess.Access.UNRESTRICTED, reason = "Allocation is fine: this method traverses only the image heap.")
505+
public boolean visitObject(Object o) {
506+
return true;
507+
}
508+
}
509+
478510
@Override
479511
public boolean walkCollectedHeapObjects(ObjectVisitor visitor) {
480512
VMOperation.guaranteeInProgressAtSafepoint("Must only be called at a safepoint");

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ protected Heap() {
9696
*/
9797
public abstract boolean walkImageHeapObjects(ObjectVisitor visitor);
9898

99+
public abstract long getImageHeapSize();
100+
99101
/**
100102
* Walk all heap objects except the native image heap objects. Must only be executed as part of
101103
* a VM operation that causes a safepoint.

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jfr/events/EveryChunkNativePeriodicEvents.java

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -124,20 +124,25 @@ private static void emitNativeMemoryTrackingEvents() {
124124
private static void emitNmtPeakEvents() {
125125
NativeMemoryUsageTotalPeakEvent nmtTotalPeakEvent = new NativeMemoryUsageTotalPeakEvent();
126126

127-
long totalPeakUsed = NativeMemoryTracking.singleton().getPeakTotalUsedMemory();
128-
nmtTotalPeakEvent.peakCommitted = totalPeakUsed;
129-
nmtTotalPeakEvent.peakReserved = totalPeakUsed;
130-
nmtTotalPeakEvent.countAtPeak = NativeMemoryTracking.singleton().getCountAtTotalPeakUsage();
127+
long totalPeakMalloc = NativeMemoryTracking.singleton().getPeakTotalMallocMemory();
128+
long totalPeakCommitted = NativeMemoryTracking.singleton().getPeakTotalCommittedVirtualMemory();
129+
long totalPeakReserved = NativeMemoryTracking.singleton().getPeakTotalReservedVirtualMemory();
130+
131+
nmtTotalPeakEvent.peakCommitted = totalPeakCommitted + totalPeakMalloc;
132+
nmtTotalPeakEvent.peakReserved = totalPeakReserved + totalPeakMalloc;
133+
nmtTotalPeakEvent.countAtPeak = NativeMemoryTracking.singleton().getCountAtPeakTotalMallocMemory();
131134
nmtTotalPeakEvent.commit();
132135

133136
for (NmtCategory nmtCategory : NmtCategory.values()) {
134137
NativeMemoryUsagePeakEvent nmtPeakEvent = new NativeMemoryUsagePeakEvent();
135138
nmtPeakEvent.type = nmtCategory.getName();
136139

137-
long peakUsed = NativeMemoryTracking.singleton().getPeakUsedMemory(nmtCategory);
138-
nmtPeakEvent.peakCommitted = peakUsed;
139-
nmtPeakEvent.peakReserved = peakUsed;
140-
nmtPeakEvent.countAtPeak = NativeMemoryTracking.singleton().getCountAtPeakUsage(nmtCategory);
140+
long peakMalloc = NativeMemoryTracking.singleton().getPeakMallocMemory(nmtCategory);
141+
long peakCommitted = NativeMemoryTracking.singleton().getPeakCommittedVirtualMemory(nmtCategory);
142+
long peakReserved = NativeMemoryTracking.singleton().getPeakReservedVirtualMemory(nmtCategory);
143+
nmtPeakEvent.peakCommitted = peakCommitted + peakMalloc;
144+
nmtPeakEvent.peakReserved = peakReserved + peakMalloc;
145+
nmtPeakEvent.countAtPeak = NativeMemoryTracking.singleton().getCountAtPeakMallocMemory(nmtCategory);
141146
nmtPeakEvent.commit();
142147
}
143148
}
@@ -150,24 +155,27 @@ private static void emitJdkNmtEvents(NmtCategory[] nmtCategories) {
150155

151156
if (JfrEvent.NativeMemoryUsage.shouldEmit()) {
152157
for (NmtCategory nmtCategory : nmtCategories) {
153-
long usedMemory = NativeMemoryTracking.singleton().getUsedMemory(nmtCategory);
158+
long mallocMemory = NativeMemoryTracking.singleton().getMallocMemory(nmtCategory);
159+
long committedVM = NativeMemoryTracking.singleton().getCommittedVirtualMemory(nmtCategory);
160+
long reservedVM = NativeMemoryTracking.singleton().getReservedVirtualMemory(nmtCategory);
154161

155162
JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.NativeMemoryUsage);
156163
JfrNativeEventWriter.putLong(data, timestamp);
157164
JfrNativeEventWriter.putLong(data, nmtCategory.ordinal());
158-
JfrNativeEventWriter.putLong(data, usedMemory); // reserved
159-
JfrNativeEventWriter.putLong(data, usedMemory); // committed
165+
JfrNativeEventWriter.putLong(data, mallocMemory + reservedVM);
166+
JfrNativeEventWriter.putLong(data, mallocMemory + committedVM);
160167
JfrNativeEventWriter.endSmallEvent(data);
161168
}
162169
}
163170

164171
if (JfrEvent.NativeMemoryUsageTotal.shouldEmit()) {
165-
long totalUsedMemory = NativeMemoryTracking.singleton().getTotalUsedMemory();
166-
172+
long totalMallocMemory = NativeMemoryTracking.singleton().getTotalMallocMemory();
173+
long totalCommittedVM = NativeMemoryTracking.singleton().getTotalCommittedVirtualMemory();
174+
long totalReservedVM = NativeMemoryTracking.singleton().getTotalReservedVirtualMemory();
167175
JfrNativeEventWriter.beginSmallEvent(data, JfrEvent.NativeMemoryUsageTotal);
168176
JfrNativeEventWriter.putLong(data, timestamp);
169-
JfrNativeEventWriter.putLong(data, totalUsedMemory); // reserved
170-
JfrNativeEventWriter.putLong(data, totalUsedMemory); // committed
177+
JfrNativeEventWriter.putLong(data, totalMallocMemory + totalReservedVM);
178+
JfrNativeEventWriter.putLong(data, totalMallocMemory + totalCommittedVM);
171179
JfrNativeEventWriter.endSmallEvent(data);
172180
}
173181
}

0 commit comments

Comments
 (0)