Skip to content

Commit 86975d6

Browse files
committed
8293503: gc/metaspace/TestMetaspacePerfCounters.java#Epsilon-64 failed assertGreaterThanOrEqual: expected MMM >= NNN
Reviewed-by: mdoerr, rrich Backport-of: 04d7b7d5747d887e12797df8ca3f7608d73d41ff
1 parent fd50c17 commit 86975d6

File tree

1 file changed

+63
-55
lines changed

1 file changed

+63
-55
lines changed

test/hotspot/jtreg/gc/metaspace/TestMetaspacePerfCounters.java

+63-55
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
package gc.metaspace;
2525

26-
import java.lang.management.GarbageCollectorMXBean;
26+
import java.lang.invoke.VarHandle;
2727
import java.util.List;
2828
import java.util.ArrayList;
2929

@@ -183,10 +183,44 @@
183183
* @run main/othervm -XX:+UsePerfData -XX:+UnlockExperimentalVMOptions -XX:+UseEpsilonGC gc.metaspace.TestMetaspacePerfCounters
184184
*/
185185

186+
class PerfCounterSnapshot {
187+
private static long getMinCapacity(String ns) throws Exception {
188+
return PerfCounters.findByName(ns + ".minCapacity").longValue();
189+
}
190+
191+
private static long getCapacity(String ns) throws Exception {
192+
return PerfCounters.findByName(ns + ".capacity").longValue();
193+
}
194+
195+
private static long getMaxCapacity(String ns) throws Exception {
196+
return PerfCounters.findByName(ns + ".maxCapacity").longValue();
197+
}
198+
199+
private static long getUsed(String ns) throws Exception {
200+
return PerfCounters.findByName(ns + ".used").longValue();
201+
}
202+
203+
public long minCapacity;
204+
public long maxCapacity;
205+
public long capacity;
206+
public long used;
207+
208+
public void get(String ns) throws Exception {
209+
minCapacity = getMinCapacity(ns);
210+
maxCapacity = getMaxCapacity(ns);
211+
used = getUsed(ns);
212+
capacity = getCapacity(ns);
213+
}
214+
215+
public boolean consistentWith(PerfCounterSnapshot other) {
216+
return (minCapacity == other.minCapacity) && (maxCapacity == other.maxCapacity) &&
217+
(used == other.used) && (capacity == other.capacity);
218+
}
219+
}
220+
186221
public class TestMetaspacePerfCounters {
187222
public static Class<?> fooClass = null;
188223
private static final String[] counterNames = {"minCapacity", "maxCapacity", "capacity", "used"};
189-
private static final List<GarbageCollectorMXBean> gcBeans = ManagementFactoryHelper.getGarbageCollectorMXBeans();
190224

191225
public static void main(String[] args) throws Exception {
192226
String metaspace = "sun.gc.metaspace";
@@ -204,32 +238,28 @@ public static void main(String[] args) throws Exception {
204238
}
205239

206240
private static void checkPerfCounters(String ns) throws Exception {
207-
long gcCountBefore;
208-
long gcCountAfter;
209-
long minCapacity;
210-
long maxCapacity;
211-
long capacity;
212-
long used;
213-
214-
// The perf counter values are updated during GC and to be able to
215-
// do the assertions below we need to ensure that the values are from
216-
// the same GC cycle.
217-
do {
218-
gcCountBefore = currentGCCount();
219-
220-
minCapacity = getMinCapacity(ns);
221-
maxCapacity = getMaxCapacity(ns);
222-
capacity = getCapacity(ns);
223-
used = getUsed(ns);
224-
225-
gcCountAfter = currentGCCount();
226-
assertGTE(gcCountAfter, gcCountBefore);
227-
} while(gcCountAfter > gcCountBefore);
228-
229-
assertGTE(minCapacity, 0L);
230-
assertGTE(used, minCapacity);
231-
assertGTE(capacity, used);
232-
assertGTE(maxCapacity, capacity);
241+
PerfCounterSnapshot snap1 = new PerfCounterSnapshot();
242+
PerfCounterSnapshot snap2 = new PerfCounterSnapshot();
243+
244+
final int MaxAttempts = 10;
245+
246+
for (int attempts = 0; ; attempts++) {
247+
snap1.get(ns);
248+
VarHandle.fullFence();
249+
snap2.get(ns);
250+
251+
if (snap1.consistentWith(snap2)) {
252+
// Got a consistent snapshot for examination.
253+
break;
254+
} else if (attempts == MaxAttempts) {
255+
throw new Exception("Failed to get stable reading of metaspace performance counters after " + attempts + " tries");
256+
}
257+
}
258+
259+
assertGTE(snap1.minCapacity, 0L);
260+
assertGTE(snap1.used, snap1.minCapacity);
261+
assertGTE(snap1.capacity, snap1.used);
262+
assertGTE(snap1.maxCapacity, snap1.capacity);
233263
}
234264

235265
private static void checkEmptyPerfCounters(String ns) throws Exception {
@@ -243,12 +273,14 @@ private static void checkUsedIncreasesWhenLoadingClass(String ns) throws Excepti
243273
// Need to ensure that used is up to date and that all unreachable
244274
// classes are unloaded before doing this check.
245275
System.gc();
246-
long before = getUsed(ns);
276+
PerfCounterSnapshot before = new PerfCounterSnapshot();
277+
before.get(ns);
247278
fooClass = compileAndLoad("Foo", "public class Foo { }");
248279
System.gc();
249-
long after = getUsed(ns);
280+
PerfCounterSnapshot after = new PerfCounterSnapshot();
281+
after.get(ns);
250282

251-
assertGT(after, before);
283+
assertGT(after.used, before.used);
252284
}
253285

254286
private static List<PerfCounter> countersInNamespace(String ns) throws Exception {
@@ -267,28 +299,4 @@ private static Class<?> compileAndLoad(String name, String source) throws Except
267299
private static boolean isUsingCompressedClassPointers() {
268300
return Platform.is64bit() && InputArguments.contains("-XX:+UseCompressedClassPointers");
269301
}
270-
271-
private static long getMinCapacity(String ns) throws Exception {
272-
return PerfCounters.findByName(ns + ".minCapacity").longValue();
273-
}
274-
275-
private static long getCapacity(String ns) throws Exception {
276-
return PerfCounters.findByName(ns + ".capacity").longValue();
277-
}
278-
279-
private static long getMaxCapacity(String ns) throws Exception {
280-
return PerfCounters.findByName(ns + ".maxCapacity").longValue();
281-
}
282-
283-
private static long getUsed(String ns) throws Exception {
284-
return PerfCounters.findByName(ns + ".used").longValue();
285-
}
286-
287-
private static long currentGCCount() {
288-
long gcCount = 0;
289-
for (GarbageCollectorMXBean bean : gcBeans) {
290-
gcCount += bean.getCollectionCount();
291-
}
292-
return gcCount;
293-
}
294302
}

0 commit comments

Comments
 (0)