diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java index 8b8fea1f2e3..2a6652eb06e 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -31,6 +31,8 @@ import com.sun.management.GarbageCollectionNotificationInfo; import java.lang.reflect.*; import java.lang.management.*; import java.util.*; +import java.util.stream.Collectors; + import javax.management.*; import javax.management.openmbean.*; import jdk.test.lib.process.ProcessTools; @@ -85,6 +87,32 @@ class TestStringDeduplicationTools { } } + /** + * Get system load. + * + *
+ *
load() ~= 1
fully loaded system, all cores are used 100%
+ *
load() < 1
some cpu resources are available
+ *
load() > 1
system is overloaded
+ *
+ * + * @return the load of the system or Optional.empty() if the load can not be determined. + */ + private static Optional systemLoad() { + OperatingSystemMXBean bean = ManagementFactory.getPlatformMXBean(OperatingSystemMXBean.class); + double average = bean.getSystemLoadAverage() / bean.getAvailableProcessors(); + return (average < 0) + ? Optional.empty() + : Optional.of(average); + } + + private static String minMax(List> l) { + DoubleSummaryStatistics minmax = l.stream().flatMap(Optional::stream).collect(Collectors.summarizingDouble(d -> d)); + return minmax.getCount() != 0 + ? "min: " + minmax.getMin() + ", max: " + minmax.getMax() + : "could not gather load statistics from system"; + } + private static void doFullGc(int numberOfTimes) { List> newStrings = new ArrayList>(); for (int i = 0; i < numberOfTimes; i++) { @@ -179,13 +207,15 @@ class TestStringDeduplicationTools { } } - private static boolean waitForDeduplication(String s1, String s2) { + private static void waitForDeduplication(String s1, String s2) { boolean first = true; int timeout = 10000; // 10sec in ms int iterationWait = 100; // 100ms + List> loadHistory = new ArrayList<>(); for (int attempts = 0; attempts < (timeout / iterationWait); attempts++) { + loadHistory.add(systemLoad()); if (getValue(s1) == getValue(s2)) { - return true; + return; } if (first) { System.out.println("Waiting for deduplication..."); @@ -194,10 +224,10 @@ class TestStringDeduplicationTools { try { Thread.sleep(iterationWait); } catch (Exception e) { - throw new RuntimeException(e); + throw new RuntimeException("Deduplication has not occurred: Thread.sleep() threw", e); } } - return false; + throw new RuntimeException("Deduplication has not occurred, load history: " + minMax(loadHistory)); } private static String generateString(int id) { @@ -240,7 +270,9 @@ class TestStringDeduplicationTools { */ private static void verifyStrings(ArrayList list, int uniqueExpected) { boolean passed = false; + List> loadHistory = new ArrayList<>(); for (int attempts = 0; attempts < 10; attempts++) { + loadHistory.add(systemLoad()); // Check number of deduplicated strings ArrayList unique = new ArrayList(uniqueExpected); for (String string: list) { @@ -277,7 +309,7 @@ class TestStringDeduplicationTools { } } if (!passed) { - throw new RuntimeException("String verification failed"); + throw new RuntimeException("String verification failed, load history: " + minMax(loadHistory)); } } @@ -361,9 +393,7 @@ class TestStringDeduplicationTools { // and be inserted into the deduplication hashtable. forceDeduplication(ageThreshold, FullGC); - if (!waitForDeduplication(dupString1, baseString)) { - throw new RuntimeException("Deduplication has not occurred"); - } + waitForDeduplication(dupString1, baseString); // Create a new duplicate of baseString StringBuilder sb2 = new StringBuilder(baseString); @@ -398,9 +428,7 @@ class TestStringDeduplicationTools { forceDeduplication(ageThreshold, FullGC); - if (!waitForDeduplication(dupString3, internedString)) { - throw new RuntimeException("Deduplication has not occurred for string 3"); - } + waitForDeduplication(dupString3, internedString); if (afterInternedValue != getValue(dupString2)) { throw new RuntimeException("Interned string value changed");