Skip to content

Commit cadcc00

Browse files
add peak tracking and associated tests
wip. Overlapping bug
1 parent 957392d commit cadcc00

File tree

7 files changed

+187
-70
lines changed

7 files changed

+187
-70
lines changed

substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/PosixVirtualMemoryProvider.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ private Pointer reserve0(UnsignedWord nbytes, UnsignedWord alignment, boolean ex
173173
}
174174
if (nmtData.isNull()) {
175175
NativeMemoryTracking.trackReserve(begin, mappingSize.subtract(unmappedSize), category);
176+
// NativeMemoryTracking.trackReserve(begin, nbytes, category); // *** didn't fix problem.
176177
} else {
177178
nmtData.setReserved(nmtData.getReserved().add(mappingSize.subtract(unmappedSize)));
178179
nmtData.setBaseAddr(begin);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/nmt/NativeMemoryTracking.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ public static long getCommittedByCategory(NmtCategory category) {
169169
return -1;
170170
}
171171

172+
public static long getPeakCommittedByCategory(NmtCategory category) {
173+
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
174+
return NativeMemoryTracking.singleton().virtualMemorySnapshot.getInfoByCategory(category).getPeakCommittedSize();
175+
}
176+
return -1;
177+
}
178+
179+
public static long getPeakReservedByCategory(NmtCategory category) {
180+
if (VMInspectionOptions.hasNativeMemoryTrackingSupport()) {
181+
return NativeMemoryTracking.singleton().virtualMemorySnapshot.getInfoByCategory(category).getPeakReservedSize();
182+
}
183+
return -1;
184+
}
185+
172186
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
173187
public void untrack(UnsignedWord size, int category) {
174188
mallocMemorySnapshot.getInfoByCategory(category).untrack(size);
@@ -207,6 +221,8 @@ public void printStatistics() {
207221
System.out.println(" Total alive malloc allocations: " + mallocMemorySnapshot.getTotalInfo().getCount());
208222
System.out.println(" Total committed memory: " + virtualMemorySnapshot.getTotalInfo().getCommittedSize() + " bytes");
209223
System.out.println(" Total reserved memory: " + virtualMemorySnapshot.getTotalInfo().getReservedSize() + " bytes");
224+
System.out.println(" Peak Total committed memory: " + virtualMemorySnapshot.getTotalInfo().getPeakCommittedSize() + " bytes");
225+
System.out.println(" Peak Total reserved memory: " + virtualMemorySnapshot.getTotalInfo().getPeakReservedSize() + " bytes");
210226

211227
for (int i = 0; i < NmtCategory.values().length; i++) {
212228
String name = NmtCategory.values()[i].getName();
@@ -217,6 +233,8 @@ public void printStatistics() {
217233
System.out.println(" " + name + " alive allocations: " + mallocInfo.getCount());
218234
System.out.println(" " + name + " committed memory: " + vMemInfo.getCommittedSize());
219235
System.out.println(" " + name + " reserved memory: " + vMemInfo.getReservedSize());
236+
System.out.println(" " + name + " peak committed memory: " + vMemInfo.getPeakCommittedSize());
237+
System.out.println(" " + name + " peak reserved memory: " + vMemInfo.getPeakReservedSize());
220238
}
221239
}
222240
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/nmt/NmtMemoryRegionListAccess.java

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -44,16 +44,16 @@ public static NmtMemoryRegion addSorted(NmtMemoryRegion listHead, NmtMemoryRegio
4444
NmtMemoryRegion prev = WordFactory.nullPointer();
4545
while (current.isNonNull()) {
4646
if (newRegion.getBaseAddr().rawValue() < current.getBaseAddr().rawValue()) {
47-
// if (NmtMemoryRegionAccess.isOverlapping(newRegion, current)){
48-
// fail42(newRegion, current);
49-
// }
47+
if (NmtMemoryRegionAccess.isOverlapping(newRegion, current)){
48+
fail42(newRegion, current);
49+
}
5050
assert !NmtMemoryRegionAccess.isOverlapping(newRegion, current);
5151
newRegion.setNext(current);
5252
if (prev.isNonNull()) {
5353
// New region is in middle of the list
54-
// if (NmtMemoryRegionAccess.isOverlapping(newRegion, prev)){
55-
// fail42(newRegion, prev);
56-
// }
54+
if (NmtMemoryRegionAccess.isOverlapping(newRegion, prev)){
55+
fail42(newRegion, prev);
56+
}
5757
assert !NmtMemoryRegionAccess.isOverlapping(newRegion, prev);
5858
prev.setNext(newRegion);
5959
return listHead;
@@ -68,9 +68,9 @@ public static NmtMemoryRegion addSorted(NmtMemoryRegion listHead, NmtMemoryRegio
6868
// New region is the new tail of the list
6969
if (prev.isNonNull()) {
7070
assert !NmtMemoryRegionAccess.isEqual(newRegion, prev);
71-
// if (NmtMemoryRegionAccess.isOverlapping(newRegion, prev)){
72-
// fail42(newRegion, prev);
73-
// }
71+
if (NmtMemoryRegionAccess.isOverlapping(newRegion, prev)){
72+
fail42(newRegion, prev);
73+
}
7474
assert !NmtMemoryRegionAccess.isOverlapping(newRegion, prev);
7575
prev.setNext(newRegion);
7676
return listHead;
@@ -80,50 +80,61 @@ public static NmtMemoryRegion addSorted(NmtMemoryRegion listHead, NmtMemoryRegio
8080
return newRegion;
8181
}
8282

83-
// @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
84-
// private static void fail42(NmtMemoryRegion newRegion, NmtMemoryRegion prev){
85-
// long size = NmtMemoryRegionAccess.getOverlapSize(newRegion, prev);
86-
// int flag = prev.getCategory();
87-
// int flagMult = flag*flag;
88-
// long mult = size*size;
89-
// assert mult <0;
90-
// assert flag<100;
91-
// }
83+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
84+
private static void fail42(NmtMemoryRegion newRegion, NmtMemoryRegion prev){
85+
long size = NmtMemoryRegionAccess.getOverlapSize(newRegion, prev);
86+
int flag = prev.getCategory();
87+
int flagMult = flag*flag;
88+
long mult = size*size;
89+
assert mult <0;
90+
assert flag<100;
91+
}
9292

9393
/** Assumes list is sorted (since it relies on findPrecedingRegion). Returns new head. */
9494
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
95-
public static NmtMemoryRegion remove(NmtMemoryRegion listHead, NmtMemoryRegion targetRegionOnStack) {
95+
public static NmtMemoryRegion remove(NmtMemoryRegion listHead, NmtMemoryRegion targetRegion) {
9696
assert listHead.isNonNull(); // There must be at least one node to remove
97-
NmtMemoryRegion prev = findPrecedingRegion(listHead, targetRegionOnStack);
97+
NmtMemoryRegion prev = findPrecedingRegion(listHead, targetRegion);
9898

9999
// Are we removing the head?
100100
if (prev.isNull()) {
101-
assert NmtMemoryRegionAccess.isEqual(listHead, targetRegionOnStack);
101+
assert NmtMemoryRegionAccess.isEqual(listHead, targetRegion);
102102
NmtMemoryRegion newHead = listHead.getNext();
103103
NullableNativeMemory.free(listHead);
104104
return newHead;
105105
}
106106

107107
// We are removing a node that is not head.
108108
NmtMemoryRegion current = prev.getNext();
109-
// assert NmtMemoryRegionAccess.isEqual(current, targetRegionOnStack);
110-
assert current.getBaseAddr() == targetRegionOnStack.getBaseAddr();
111-
assert !NmtMemoryRegionAccess.isEqual(listHead, targetRegionOnStack);
109+
// assert NmtMemoryRegionAccess.isEqual(current, targetRegion);
110+
assert current.getBaseAddr() == targetRegion.getBaseAddr();
111+
assert !NmtMemoryRegionAccess.isEqual(listHead, targetRegion);
112112
prev.setNext(current.getNext());
113113
NullableNativeMemory.free(current);
114114
return listHead;
115115
}
116116

117117
/**
118-
* Finds the region allocated on the heap that contains or matches the target region. Or nullPtr
119-
* if unsuccessful. This is useful for searching for a reserved region that a committed region
120-
* may belong to.
118+
* Finds the region that contains or matches the target region. Or nullPtr
119+
* if unsuccessful.
121120
*/
122121
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
123-
static NmtMemoryRegion findContainingRegion(NmtMemoryRegion listHead, NmtMemoryRegion targetRegionOnStack) {
122+
static NmtMemoryRegion findContainingRegion(NmtMemoryRegion listHead, NmtMemoryRegion targetRegion) {
123+
NmtMemoryRegion current = listHead;
124+
while (current.isNonNull()) {
125+
if (NmtMemoryRegionAccess.contains(current, targetRegion)) {
126+
return current;
127+
}
128+
current = current.getNext();
129+
}
130+
return WordFactory.nullPointer();
131+
}
132+
133+
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
134+
static NmtMemoryRegion findRegionMatchingBase(NmtMemoryRegion listHead, org.graalvm.word.PointerBase baseAddr ) {
124135
NmtMemoryRegion current = listHead;
125136
while (current.isNonNull()) {
126-
if (NmtMemoryRegionAccess.contains(current, targetRegionOnStack)) {
137+
if (current.getBaseAddr().rawValue() == baseAddr.rawValue()) {
127138
return current;
128139
}
129140
current = current.getNext();
@@ -133,12 +144,12 @@ static NmtMemoryRegion findContainingRegion(NmtMemoryRegion listHead, NmtMemoryR
133144

134145
/** Assumes list is sorted. */
135146
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
136-
static NmtMemoryRegion findPrecedingRegion(NmtMemoryRegion listHead, NmtMemoryRegion targetRegionOnStack) {
147+
static NmtMemoryRegion findPrecedingRegion(NmtMemoryRegion listHead, NmtMemoryRegion targetRegion) {
137148
NmtMemoryRegion current = listHead;
138149
NmtMemoryRegion preceding = WordFactory.nullPointer();
139150
while (current.isNonNull()) {
140151
long currentEnd = current.getBaseAddr().rawValue() + current.getSize();
141-
if (currentEnd > targetRegionOnStack.getBaseAddr().rawValue()) { // *** should this be
152+
if (currentEnd > targetRegion.getBaseAddr().rawValue()) { // *** should this be
142153
// >=??? [NO. Since end
143154
// is non-inclusive.
144155
// draw it out. This

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/nmt/NmtVirtualMemoryInfo.java

Lines changed: 53 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,15 +26,24 @@
2626

2727
package com.oracle.svm.core.nmt;
2828

29+
import static com.oracle.svm.core.Uninterruptible.CALLED_FROM_UNINTERRUPTIBLE_CODE;
30+
2931
import com.oracle.svm.core.Uninterruptible;
3032
import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicLong;
3133
import org.graalvm.nativeimage.Platform;
3234
import org.graalvm.nativeimage.Platforms;
3335
import org.graalvm.word.UnsignedWord;
36+
import jdk.internal.misc.Unsafe;
3437

3538
class NmtVirtualMemoryInfo {
39+
40+
private static final Unsafe U = Unsafe.getUnsafe();
41+
protected static final long PEAK_RESERVED_OFFSET = U.objectFieldOffset(NmtVirtualMemoryInfo.class, "peakReservedSize");
42+
protected static final long PEAK_COMMITTED_OFFSET = U.objectFieldOffset(NmtVirtualMemoryInfo.class, "peakCommittedSize");
3643
private AtomicLong reservedSize;
3744
private AtomicLong committedSize;
45+
private volatile long peakReservedSize;
46+
private volatile long peakCommittedSize;
3847

3948
@Platforms(Platform.HOSTED_ONLY.class)
4049
NmtVirtualMemoryInfo() {
@@ -44,31 +53,70 @@ class NmtVirtualMemoryInfo {
4453

4554
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
4655
void trackReserved(UnsignedWord size) {
47-
reservedSize.addAndGet(size.rawValue());
56+
updatePeakReserved(reservedSize.addAndGet(size.rawValue()));
57+
4858
}
4959

50-
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
60+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
5161
void trackCommitted(UnsignedWord size) {
52-
long lastCommitted = committedSize.addAndGet(size.rawValue());
62+
updatePeakCommitted(committedSize.addAndGet(size.rawValue()));
5363
}
5464

55-
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
65+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
5666
void trackUncommit(long size) {
5767
long lastSize = committedSize.addAndGet(-size);
5868
assert lastSize >= 0;
69+
5970
}
6071

61-
@Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true)
72+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
6273
void trackFree(long size) {
6374
long lastSize = reservedSize.addAndGet(-size);
6475
assert lastSize >= 0;
6576
}
6677

78+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
79+
private void updatePeakReserved(long newValue) {
80+
long expectedPeak = peakReservedSize;
81+
while (expectedPeak < newValue) {
82+
if (U.compareAndSetLong(this, PEAK_RESERVED_OFFSET, expectedPeak, newValue)) { // TODO
83+
// use
84+
// compare
85+
// and
86+
// set in
87+
// other
88+
// PR
89+
// too!
90+
return;
91+
}
92+
expectedPeak = peakReservedSize;
93+
}
94+
}
95+
96+
@Uninterruptible(reason = CALLED_FROM_UNINTERRUPTIBLE_CODE, mayBeInlined = true)
97+
private void updatePeakCommitted(long newValue) {
98+
long expectedPeak = peakCommittedSize;
99+
while (expectedPeak < newValue) {
100+
if (U.compareAndSetLong(this, PEAK_COMMITTED_OFFSET, expectedPeak, newValue)) {
101+
return;
102+
}
103+
expectedPeak = peakCommittedSize;
104+
}
105+
}
106+
67107
long getReservedSize() {
68108
return reservedSize.get();
69109
}
70110

71111
long getCommittedSize() {
72112
return committedSize.get();
73113
}
114+
115+
long getPeakReservedSize() {
116+
return peakReservedSize;
117+
}
118+
119+
long getPeakCommittedSize() {
120+
return peakCommittedSize;
121+
}
74122
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/nmt/NmtVirtualMemoryTracker.java

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,7 @@ private void trackUncommit0(long size, int category) {
330330
}
331331

332332
/**
333-
* It is guranteed that exactly the entire reserved region is freed. See
333+
* It is guaranteed that exactly the entire reserved region is requested to be freed. See
334334
* {@link com.oracle.svm.core.os.VirtualMemoryProvider#free(PointerBase, UnsignedWord)}.
335335
*/
336336
@BasedOnJDKFile("https://github.com/openjdk/jdk/blob/jdk-23+13/src/hotspot/share/nmt/virtualMemoryTracker.cpp#L491-L533")
@@ -346,15 +346,19 @@ void trackFree(PointerBase baseAddr, UnsignedWord size) {
346346
targetRegion.setBaseAddr(baseAddr);
347347

348348
/* Find the reserved region so we can access its committed list. */
349-
NmtReservedRegion reservedRegion = (NmtReservedRegion) NmtMemoryRegionListAccess.findContainingRegion(reservedRegionListHead, targetRegion);
349+
NmtReservedRegion reservedRegion = (NmtReservedRegion) NmtMemoryRegionListAccess.findRegionMatchingBase(reservedRegionListHead, baseAddr);
350+
// NmtReservedRegion reservedRegion = (NmtReservedRegion) NmtMemoryRegionListAccess.findContainingRegion(reservedRegionListHead, targetRegion);//TODO uncomment
350351

351-
assert reservedRegion.isNonNull();
352-
assert NmtMemoryRegionAccess.isEqual(reservedRegion, targetRegion);
352+
assert reservedRegion.isNonNull(); // *** This still sometimes fails!!!
353+
// assert NmtMemoryRegionAccess.isEqual(reservedRegion, targetRegion); //TODO uncomment
354+
assert targetRegion.getBaseAddr().rawValue() == reservedRegion.getBaseAddr().rawValue(); //TODO uncomment
353355

354-
removeUncommittedRegion(reservedRegion, targetRegion);
356+
removeUncommittedRegion(reservedRegion, reservedRegion);
357+
// removeUncommittedRegion(reservedRegion, targetRegion);//TODO uncomment fails when applied
355358

356359
trackFree0(size.rawValue(), reservedRegion.getCategory());
357-
reservedRegionListHead = (NmtReservedRegion) NmtMemoryRegionListAccess.remove(reservedRegionListHead, targetRegion);
360+
// reservedRegionListHead = (NmtReservedRegion) NmtMemoryRegionListAccess.remove(reservedRegionListHead, targetRegion);//TODO uncomment
361+
reservedRegionListHead = (NmtReservedRegion) NmtMemoryRegionListAccess.remove(reservedRegionListHead, reservedRegion);
358362
assert NmtMemoryRegionListAccess.verifyReservedList(reservedRegionListHead);
359363

360364
} finally {
@@ -382,14 +386,16 @@ private void unlock() {
382386
void teardown() {
383387
lockNoTransition();
384388
try {
385-
NmtMemoryRegion current = reservedRegionListHead;
389+
NmtReservedRegion current = reservedRegionListHead;
386390

387391
while (current.isNonNull()) {
388-
NmtMemoryRegion next = current.getNext();
389-
NmtMemoryRegionListAccess.teardown(current);
392+
NmtReservedRegion next = (NmtReservedRegion) current.getNext();
393+
NmtMemoryRegionListAccess.teardown(current.getCommittedRegions());
394+
current.setCommittedRegions(WordFactory.nullPointer());
390395
current = next;
391396
}
392397
NmtMemoryRegionListAccess.teardown(reservedRegionListHead);
398+
reservedRegionListHead = WordFactory.nullPointer();
393399
tornDown = true;
394400
} finally {
395401
unlock();

0 commit comments

Comments
 (0)