8188245: [Testbug] test/hotspot/jtreg/gc/logging/TestPrintReferences.java can fail
Summary: Changed to use BigDecimal to solve double rounding issue
Reviewed-by: sjohanss, eosterlund
--- a/test/hotspot/jtreg/ProblemList.txt Thu Oct 19 14:15:06 2017 +0200
+++ b/test/hotspot/jtreg/ProblemList.txt Thu Oct 19 11:31:52 2017 -0700
@@ -64,7 +64,6 @@
gc/g1/humongousObjects/TestHeapCounters.java 8178918 generic-all
gc/stress/gclocker/TestGCLockerWithG1.java 8179226 generic-all
gc/survivorAlignment/TestPromotionFromSurvivorToTenuredAfterMinorGC.java 8177765 generic-all
-gc/logging/TestPrintReferences.java 8188245 generic-all
#############################################################################
--- a/test/hotspot/jtreg/gc/logging/TestPrintReferences.java Thu Oct 19 14:15:06 2017 +0200
+++ b/test/hotspot/jtreg/gc/logging/TestPrintReferences.java Thu Oct 19 11:31:52 2017 -0700
@@ -23,7 +23,7 @@
/*
* @test TestPrintReferences
- * @bug 8136991 8186402 8186465
+ * @bug 8136991 8186402 8186465 8188245
* @summary Validate the reference processing logging
* @key gc
* @library /test/lib
@@ -32,6 +32,7 @@
*/
import java.lang.ref.SoftReference;
+import java.math.BigDecimal;
import java.util.ArrayList;
import jdk.test.lib.process.OutputAnalyzer;
@@ -108,7 +109,7 @@
}
// After getting time value, update 'output' for next use.
- public static double getTimeValue(String name, int indentCount) {
+ public static BigDecimal getTimeValue(String name, int indentCount) {
// Pattern of 'name', 'value' and some extra strings.
String patternString = gcLogTimeRegex + indent(indentCount) + name + ": " + "(" + doubleRegex + ")";
Matcher m = Pattern.compile(patternString).matcher(output);
@@ -126,59 +127,63 @@
output = output.substring(index, output.length());
}
- return result;
+ // Convert to BigDecimal to control the precision of floating point arithmetic.
+ return BigDecimal.valueOf(result);
}
// Reference log is printing 1 decimal place of elapsed time.
// So sum of each sub-phases could be slightly larger than the enclosing phase in some cases.
- // As the maximum of sub-phases is 3, allow 0.1 of TOLERANCE.
- // e.g. Actual value: SoftReference(5.55) = phase1(1.85) + phase2(1.85) + phase3(1.85)
+ // e.g. If there are 3 sub-phases:
+ // Actual value: SoftReference(5.55) = phase1(1.85) + phase2(1.85) + phase3(1.85)
// Log value: SoftReference(5.6) = phase1(1.9) + phase2(1.9) + phase3(1.9)
// When checked: 5.6 < 5.7 (sum of phase1~3)
- public static boolean approximatelyEqual(double a, double b) {
- final double TOLERANCE = 0.1;
+ public static boolean approximatelyEqual(BigDecimal phaseTime, BigDecimal sumOfSubPhasesTime, BigDecimal tolerance) {
+ BigDecimal abs = phaseTime.subtract(sumOfSubPhasesTime).abs();
+
+ int result = abs.compareTo(tolerance);
- return Math.abs(a - b) <= TOLERANCE;
- }
-
- // Return false, if 'total' is larger and not approximately equal to 'refTime'.
- public static boolean compare(double refTime, double total) {
- return (refTime < total) && (!approximatelyEqual(refTime, total));
+ // result == -1, abs is less than tolerance.
+ // result == 0, abs is equal to tolerance.
+ // result == 1, abs is greater than tolerance.
+ return (result != 1);
}
- public static double checkRefTime(String refType) {
- double refTime = getTimeValue(refType, 2);
- double total = 0.0;
+ public static BigDecimal checkPhaseTime(String refType) {
+ BigDecimal phaseTime = getTimeValue(refType, 2);
+ BigDecimal sumOfSubPhasesTime = BigDecimal.valueOf(0.0);
if (softReference.equals(refType)) {
- total += getTimeValue(phase1, 4);
+ sumOfSubPhasesTime = sumOfSubPhasesTime.add(getTimeValue(phase1, 4));
}
- total += getTimeValue(phase2, 4);
- total += getTimeValue(phase3, 4);
+ sumOfSubPhasesTime = sumOfSubPhasesTime.add(getTimeValue(phase2, 4));
+ sumOfSubPhasesTime = sumOfSubPhasesTime.add(getTimeValue(phase3, 4));
- if (compare(refTime, total)) {
- throw new RuntimeException(refType +" time(" + refTime +
- "ms) is less than the sum(" + total + "ms) of each phases");
+ // If there are 3 sub-phases, we should allow 0.1 tolerance.
+ final BigDecimal toleranceFor3SubPhases = BigDecimal.valueOf(0.1);
+ if (!approximatelyEqual(phaseTime, sumOfSubPhasesTime, toleranceFor3SubPhases)) {
+ throw new RuntimeException(refType +" time(" + phaseTime +
+ "ms) is less than the sum(" + sumOfSubPhasesTime + "ms) of each phases");
}
- return refTime;
+ return phaseTime;
}
- // Find the first concurrent Reference Processing log and compare sub-time vs. total.
+ // Find the first concurrent Reference Processing log and compare phase time vs. sum of sub-phases.
public static void checkLogValue(OutputAnalyzer out) {
output = out.getStdout();
- double refProcTime = getTimeValue(referenceProcessing, 0);
+ BigDecimal refProcTime = getTimeValue(referenceProcessing, 0);
- double total = 0.0;
- total += checkRefTime(softReference);
- total += checkRefTime(weakReference);
- total += checkRefTime(finalReference);
- total += checkRefTime(phantomReference);
+ BigDecimal sumOfSubPhasesTime = checkPhaseTime(softReference);
+ sumOfSubPhasesTime = sumOfSubPhasesTime.add(checkPhaseTime(weakReference));
+ sumOfSubPhasesTime = sumOfSubPhasesTime.add(checkPhaseTime(finalReference));
+ sumOfSubPhasesTime = sumOfSubPhasesTime.add(checkPhaseTime(phantomReference));
- if (compare(refProcTime, total)) {
+ // If there are 4 sub-phases, we should allow 0.2 tolerance.
+ final BigDecimal toleranceFor4SubPhases = BigDecimal.valueOf(0.2);
+ if (!approximatelyEqual(refProcTime, sumOfSubPhasesTime, toleranceFor4SubPhases)) {
throw new RuntimeException("Reference Processing time(" + refProcTime + "ms) is less than the sum("
- + total + "ms) of each phases");
+ + sumOfSubPhasesTime + "ms) of each phases");
}
}