8129937: compiler/codecache/jmx/UsageThresholdIncreasedTest.java fails with "Usage threshold was hit"

Tests should not assume that usage of non-profiled code heap is predictable.

Reviewed-by: kvn, dpochepk
This commit is contained in:
Tobias Hartmann 2015-07-01 09:07:10 +02:00
parent 4a826139e3
commit fba308328b
8 changed files with 64 additions and 56 deletions

View file

@ -21,6 +21,7 @@
* questions. * questions.
*/ */
import jdk.test.lib.Asserts;
import jdk.test.lib.Utils; import jdk.test.lib.Utils;
import java.lang.management.MemoryPoolMXBean; import java.lang.management.MemoryPoolMXBean;
import javax.management.Notification; import javax.management.Notification;
@ -80,19 +81,42 @@ public final class CodeCacheUtils {
} }
/** /**
* A "non-nmethods" code heap is used by interpreter during bytecode * Checks if the usage of the code heap corresponding to 'btype' can be
* execution, thus, it can't be predicted if this code heap usage will be * predicted at runtime if we disable compilation. The usage of the
* increased or not. Same goes for 'All'. * 'NonNMethod' code heap can not be predicted because we generate adapters
* and buffers at runtime. The 'MethodNonProfiled' code heap is also not
* predictable because we may generate compiled versions of method handle
* intrinsics while resolving methods at runtime. Same applies to 'All'.
* *
* @param btype BlobType to be checked * @param btype BlobType to be checked
* @return boolean value, true if respective code heap is predictable * @return boolean value, true if respective code heap is predictable
*/ */
public static boolean isCodeHeapPredictable(BlobType btype) { public static boolean isCodeHeapPredictable(BlobType btype) {
return btype == BlobType.MethodNonProfiled return btype == BlobType.MethodProfiled;
|| btype == BlobType.MethodProfiled;
} }
public static void disableCollectionUsageThresholds(){ /**
* Verifies that 'newValue' is equal to 'oldValue' if usage of the
* corresponding code heap is predictable. Checks the weaker condition
* 'newValue >= oldValue' if usage is not predictable because intermediate
* allocations may happen.
*
* @param btype BlobType of the code heap to be checked
* @param newValue New value to be verified
* @param oldValue Old value to be verified
* @param msg Error message if verification fails
*/
public static void assertEQorGTE(BlobType btype, long newValue, long oldValue, String msg) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
// Usage is predictable, check strong == condition
Asserts.assertEQ(newValue, oldValue, msg);
} else {
// Usage is not predictable, check weaker >= condition
Asserts.assertGTE(newValue, oldValue, msg);
}
}
public static void disableCollectionUsageThresholds() {
BlobType.getAvailable().stream() BlobType.getAvailable().stream()
.map(BlobType::getMemoryPool) .map(BlobType::getMemoryPool)
.filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported) .filter(MemoryPoolMXBean::isCollectionUsageThresholdSupported)

View file

@ -52,10 +52,8 @@ public class GetUsageTest {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
for (BlobType btype : BlobType.getAvailable()) { for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) { for (int allocSize = 10; allocSize < 100000; allocSize *= 10) {
for (int allocSize = 10; allocSize < 100000; allocSize *= 10) { new GetUsageTest(btype, allocSize).runTest();
new GetUsageTest(btype, allocSize).runTest();
}
} }
} }
} }
@ -87,13 +85,15 @@ public class GetUsageTest {
for (MemoryPoolMXBean entry : predictableBeans) { for (MemoryPoolMXBean entry : predictableBeans) {
long diff = current.get(entry) - initial.get(entry); long diff = current.get(entry) - initial.get(entry);
if (entry.equals(btype.getMemoryPool())) { if (entry.equals(btype.getMemoryPool())) {
Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate, if (CodeCacheUtils.isCodeHeapPredictable(btype)) {
String.format("Pool %s usage increase was reported " Asserts.assertFalse(diff <= 0L || diff > usageUpperEstimate,
+ "unexpectedly as increased by %d using " String.format("Pool %s usage increase was reported "
+ "allocation size %d", entry.getName(), + "unexpectedly as increased by %d using "
diff, allocateSize)); + "allocation size %d", entry.getName(),
diff, allocateSize));
}
} else { } else {
Asserts.assertEQ(diff, 0L, CodeCacheUtils.assertEQorGTE(btype, diff, 0L,
String.format("Pool %s usage changed unexpectedly while" String.format("Pool %s usage changed unexpectedly while"
+ " trying to increase: %s using allocation " + " trying to increase: %s using allocation "
+ "size %d", entry.getName(), + "size %d", entry.getName(),

View file

@ -52,9 +52,7 @@ public class PeakUsageTest {
public static void main(String[] args) { public static void main(String[] args) {
for (BlobType btype : BlobType.getAvailable()) { for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) { new PeakUsageTest(btype).runTest();
new PeakUsageTest(btype).runTest();
}
} }
} }
@ -65,7 +63,7 @@ public class PeakUsageTest {
CodeCacheUtils.ALLOCATION_SIZE, btype.id); CodeCacheUtils.ALLOCATION_SIZE, btype.id);
long newPeakUsage = bean.getPeakUsage().getUsed(); long newPeakUsage = bean.getPeakUsage().getUsed();
try { try {
Asserts.assertEQ(newPeakUsage, bean.getUsage().getUsed(), CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getUsage().getUsed(),
"Peak usage does not match usage after allocation for " "Peak usage does not match usage after allocation for "
+ bean.getName()); + bean.getName());
} finally { } finally {
@ -73,18 +71,18 @@ public class PeakUsageTest {
CodeCacheUtils.WB.freeCodeBlob(addr); CodeCacheUtils.WB.freeCodeBlob(addr);
} }
} }
Asserts.assertEQ(newPeakUsage, bean.getPeakUsage().getUsed(), CodeCacheUtils.assertEQorGTE(btype, newPeakUsage, bean.getPeakUsage().getUsed(),
"Code cache peak usage has changed after usage decreased for " "Code cache peak usage has changed after usage decreased for "
+ bean.getName()); + bean.getName());
bean.resetPeakUsage(); bean.resetPeakUsage();
Asserts.assertEQ(bean.getPeakUsage().getUsed(), CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(),
bean.getUsage().getUsed(), bean.getUsage().getUsed(),
"Code cache peak usage is not equal to usage after reset for " "Code cache peak usage is not equal to usage after reset for "
+ bean.getName()); + bean.getName());
long addr2 = CodeCacheUtils.WB.allocateCodeBlob( long addr2 = CodeCacheUtils.WB.allocateCodeBlob(
CodeCacheUtils.ALLOCATION_SIZE, btype.id); CodeCacheUtils.ALLOCATION_SIZE, btype.id);
try { try {
Asserts.assertEQ(bean.getPeakUsage().getUsed(), CodeCacheUtils.assertEQorGTE(btype, bean.getPeakUsage().getUsed(),
bean.getUsage().getUsed(), bean.getUsage().getUsed(),
"Code cache peak usage is not equal to usage after fresh " "Code cache peak usage is not equal to usage after fresh "
+ "allocation for " + bean.getName()); + "allocation for " + bean.getName());

View file

@ -97,13 +97,11 @@ public class PoolsIndependenceTest implements NotificationListener {
return false; return false;
}); });
for (BlobType bt : BlobType.getAvailable()) { for (BlobType bt : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(bt)) { int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0;
int expectedNotificationsAmount = bt.equals(btype) ? 1 : 0; CodeCacheUtils.assertEQorGTE(btype, counters.get(bt.getMemoryPool().getName()).get(),
Asserts.assertEQ(counters.get(bt.getMemoryPool().getName()).get(), expectedNotificationsAmount, String.format("Unexpected "
expectedNotificationsAmount, String.format("Unexpected " + "amount of notifications for pool: %s",
+ "amount of notifications for pool: %s", bt.getMemoryPool().getName()));
bt.getMemoryPool().getName()));
}
} }
try { try {
((NotificationEmitter) ManagementFactory.getMemoryMXBean()). ((NotificationEmitter) ManagementFactory.getMemoryMXBean()).

View file

@ -54,9 +54,7 @@ public class ThresholdNotificationsTest implements NotificationListener {
public static void main(String[] args) { public static void main(String[] args) {
for (BlobType bt : BlobType.getAvailable()) { for (BlobType bt : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(bt)) { new ThresholdNotificationsTest(bt).runTest();
new ThresholdNotificationsTest(bt).runTest();
}
} }
} }
@ -92,7 +90,9 @@ public class ThresholdNotificationsTest implements NotificationListener {
} }
Asserts.assertTrue( Asserts.assertTrue(
Utils.waitForCondition( Utils.waitForCondition(
() -> counter == iterationsCount, WAIT_TIME), () -> (CodeCacheUtils.isCodeHeapPredictable(btype) ?
(counter == iterationsCount) : (counter >= iterationsCount)),
WAIT_TIME),
"Couldn't receive expected notifications count"); "Couldn't receive expected notifications count");
try { try {
((NotificationEmitter) ManagementFactory.getMemoryMXBean()). ((NotificationEmitter) ManagementFactory.getMemoryMXBean()).

View file

@ -51,13 +51,9 @@ public class UsageThresholdExceededTest {
} }
public static void main(String[] args) { public static void main(String[] args) {
int iterationsCount = int iterationsCount = Integer.getInteger("jdk.test.lib.iterations", 1);
Integer.getInteger("jdk.test.lib.iterations", 1);
for (BlobType btype : BlobType.getAvailable()) { for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) { new UsageThresholdExceededTest(btype, iterationsCount).runTest();
new UsageThresholdExceededTest(btype, iterationsCount)
.runTest();
}
} }
} }
@ -67,9 +63,8 @@ public class UsageThresholdExceededTest {
for (int i = 0; i < iterations; i++) { for (int i = 0; i < iterations; i++) {
CodeCacheUtils.hitUsageThreshold(bean, btype); CodeCacheUtils.hitUsageThreshold(bean, btype);
} }
Asserts.assertEQ(bean.getUsageThresholdCount(), oldValue + iterations, CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), oldValue + iterations,
"Unexpected threshold usage count"); "Unexpected threshold usage count");
System.out.printf("INFO: Scenario finished successfully for %s%n", System.out.printf("INFO: Scenario finished successfully for %s%n", bean.getName());
bean.getName());
} }
} }

View file

@ -27,7 +27,6 @@ import sun.hotspot.code.BlobType;
/* /*
* @test UsageThresholdIncreasedTest * @test UsageThresholdIncreasedTest
* @ignore 8129937
* @library /testlibrary /../../test/lib * @library /testlibrary /../../test/lib
* @modules java.base/sun.misc * @modules java.base/sun.misc
* java.management * java.management
@ -54,14 +53,12 @@ public class UsageThresholdIncreasedTest {
public static void main(String[] args) { public static void main(String[] args) {
for (BlobType btype : BlobType.getAvailable()) { for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) { new UsageThresholdIncreasedTest(btype).runTest();
new UsageThresholdIncreasedTest(btype).runTest();
}
} }
} }
private void checkUsageThresholdCount(MemoryPoolMXBean bean, long count){ private void checkUsageThresholdCount(MemoryPoolMXBean bean, long count){
Asserts.assertEQ(bean.getUsageThresholdCount(), count, CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), count,
String.format("Usage threshold was hit: %d times for %s " String.format("Usage threshold was hit: %d times for %s "
+ "Threshold value: %d with current usage: %d", + "Threshold value: %d with current usage: %d",
bean.getUsageThresholdCount(), bean.getName(), bean.getUsageThresholdCount(), bean.getName(),

View file

@ -50,9 +50,7 @@ public class UsageThresholdNotExceededTest {
public static void main(String[] args) { public static void main(String[] args) {
for (BlobType btype : BlobType.getAvailable()) { for (BlobType btype : BlobType.getAvailable()) {
if (CodeCacheUtils.isCodeHeapPredictable(btype)) { new UsageThresholdNotExceededTest(btype).runTest();
new UsageThresholdNotExceededTest(btype).runTest();
}
} }
} }
@ -65,13 +63,11 @@ public class UsageThresholdNotExceededTest {
- CodeCacheUtils.getHeaderSize(btype), btype.id); - CodeCacheUtils.getHeaderSize(btype), btype.id);
// a gc cycle triggers usage threshold recalculation // a gc cycle triggers usage threshold recalculation
CodeCacheUtils.WB.fullGC(); CodeCacheUtils.WB.fullGC();
Asserts.assertEQ(bean.getUsageThresholdCount(), initialThresholdCount, CodeCacheUtils.assertEQorGTE(btype, bean.getUsageThresholdCount(), initialThresholdCount,
String.format("Usage threshold was hit: %d times for %s. " String.format("Usage threshold was hit: %d times for %s. "
+ "Threshold value: %d with current usage: %d", + "Threshold value: %d with current usage: %d",
bean.getUsageThresholdCount(), bean.getName(), bean.getUsageThresholdCount(), bean.getName(),
bean.getUsageThreshold(), bean.getUsage().getUsed())); bean.getUsageThreshold(), bean.getUsage().getUsed()));
System.out.println("INFO: Case finished successfully for " + bean.getName());
System.out.println("INFO: Case finished successfully for "
+ bean.getName());
} }
} }