26 * @summary Check if the space utilization for shared spaces is adequate |
26 * @summary Check if the space utilization for shared spaces is adequate |
27 * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) |
27 * @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true) |
28 * @library /test/lib |
28 * @library /test/lib |
29 * @modules java.base/jdk.internal.misc |
29 * @modules java.base/jdk.internal.misc |
30 * java.management |
30 * java.management |
31 * @run main SpaceUtilizationCheck |
31 * @build sun.hotspot.WhiteBox |
|
32 * @run main ClassFileInstaller sun.hotspot.WhiteBox |
|
33 * sun.hotspot.WhiteBox$WhiteBoxPermission |
|
34 * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI SpaceUtilizationCheck |
32 */ |
35 */ |
33 |
36 |
34 import jdk.test.lib.cds.CDSTestUtils; |
37 import jdk.test.lib.cds.CDSTestUtils; |
35 import jdk.test.lib.process.OutputAnalyzer; |
38 import jdk.test.lib.process.OutputAnalyzer; |
|
39 import sun.hotspot.WhiteBox; |
36 |
40 |
37 import java.util.regex.Pattern; |
41 import java.util.regex.Pattern; |
38 import java.util.regex.Matcher; |
42 import java.util.regex.Matcher; |
39 import java.util.ArrayList; |
43 import java.util.ArrayList; |
|
44 import java.util.Hashtable; |
40 import java.lang.Integer; |
45 import java.lang.Integer; |
41 |
46 |
42 public class SpaceUtilizationCheck { |
47 public class SpaceUtilizationCheck { |
43 // Minimum allowed utilization value (percent) |
48 // [1] Each region must have strictly less than |
44 // The goal is to have this number to be 50% for RO and RW regions |
49 // WhiteBox.metaspaceReserveAlignment() bytes of unused space. |
45 // Once that feature is implemented, increase the MIN_UTILIZATION to 50 |
50 // [2] There must be no gap between two consecutive regions. |
46 private static final int MIN_UTILIZATION = 30; |
|
47 |
|
48 // Only RO and RW regions are considered for this check, since they |
|
49 // currently account for the bulk of the shared space |
|
50 private static final int NUMBER_OF_CHECKED_SHARED_REGIONS = 2; |
|
51 |
51 |
52 public static void main(String[] args) throws Exception { |
52 public static void main(String[] args) throws Exception { |
53 OutputAnalyzer output = CDSTestUtils.createArchive(); |
53 // (1) Default VM arguments |
|
54 test(); |
|
55 |
|
56 // (2) Use the now deprecated VM arguments. They should have no effect. |
|
57 test("-XX:SharedReadWriteSize=128M", |
|
58 "-XX:SharedReadOnlySize=128M", |
|
59 "-XX:SharedMiscDataSize=128M", |
|
60 "-XX:SharedMiscCodeSize=128M"); |
|
61 } |
|
62 |
|
63 static void test(String... extra_options) throws Exception { |
|
64 OutputAnalyzer output = CDSTestUtils.createArchive(extra_options); |
54 CDSTestUtils.checkDump(output); |
65 CDSTestUtils.checkDump(output); |
|
66 Pattern pattern = Pattern.compile("^(..) space: *([0-9]+).* out of *([0-9]+) bytes .* at 0x([0-9a0-f]+)"); |
|
67 WhiteBox wb = WhiteBox.getWhiteBox(); |
|
68 long reserve_alignment = wb.metaspaceReserveAlignment(); |
|
69 System.out.println("Metaspace::reserve_alignment() = " + reserve_alignment); |
55 |
70 |
56 String stdout = output.getStdout(); |
71 long last_region = -1; |
57 ArrayList<String> utilization = findUtilization(stdout); |
72 Hashtable<String,String> checked = new Hashtable<>(); |
58 |
73 for (String line : output.getStdout().split("\n")) { |
59 if (utilization.size() != NUMBER_OF_CHECKED_SHARED_REGIONS ) |
74 if (line.contains(" space:") && !line.contains("st space:")) { |
60 throw new RuntimeException("The output format of sharing summary has changed"); |
75 Matcher matcher = pattern.matcher(line); |
61 |
76 if (matcher.find()) { |
62 for(String str : utilization) { |
77 String name = matcher.group(1); |
63 int value = Integer.parseInt(str); |
78 if (name.equals("s0") || name.equals("s1")) { |
64 if (value < MIN_UTILIZATION) { |
79 // String regions are listed at the end and they may not be fully occupied. |
65 System.out.println(stdout); |
80 break; |
66 throw new RuntimeException("Utilization for one of the regions" + |
81 } else { |
67 "is below a threshold of " + MIN_UTILIZATION + "%"); |
82 System.out.println("Checking " + name + " in : " + line); |
|
83 checked.put(name, name); |
|
84 } |
|
85 long used = Long.parseLong(matcher.group(2)); |
|
86 long capacity = Long.parseLong(matcher.group(3)); |
|
87 long address = Long.parseLong(matcher.group(4), 16); |
|
88 long unused = capacity - used; |
|
89 if (unused < 0) { |
|
90 throw new RuntimeException("Unused space (" + unused + ") less than 0"); |
|
91 } |
|
92 if (unused > reserve_alignment) { |
|
93 // [1] Check for unused space |
|
94 throw new RuntimeException("Unused space (" + unused + ") must be smaller than Metaspace::reserve_alignment() (" + |
|
95 reserve_alignment + ")"); |
|
96 } |
|
97 if (last_region >= 0 && address != last_region) { |
|
98 // [2] Check for no-gap |
|
99 throw new RuntimeException("Region 0x" + address + " should have started at 0x" + Long.toString(last_region, 16)); |
|
100 } |
|
101 last_region = address + capacity; |
|
102 } |
68 } |
103 } |
69 } |
104 } |
70 } |
105 if (checked.size() != 5) { |
71 |
106 throw new RuntimeException("Must have 5 consecutive, fully utilized regions"); |
72 public static ArrayList<String> findUtilization(String input) { |
|
73 ArrayList<String> regions = filterRegionsOfInterest(input.split("\n")); |
|
74 return filterByPattern(filterByPattern(regions, "bytes \\[.*% used\\]"), "\\d+"); |
|
75 } |
|
76 |
|
77 private static ArrayList<String> filterByPattern(Iterable<String> input, String pattern) { |
|
78 ArrayList<String> result = new ArrayList<String>(); |
|
79 for (String str : input) { |
|
80 Matcher matcher = Pattern.compile(pattern).matcher(str); |
|
81 if (matcher.find()) { |
|
82 result.add(matcher.group()); |
|
83 } |
|
84 } |
107 } |
85 return result; |
|
86 } |
|
87 |
|
88 private static ArrayList<String> filterRegionsOfInterest(String[] inputLines) { |
|
89 ArrayList<String> result = new ArrayList<String>(); |
|
90 for (String str : inputLines) { |
|
91 if (str.contains("ro space:") || str.contains("rw space:")) { |
|
92 result.add(str); |
|
93 } |
|
94 } |
|
95 return result; |
|
96 } |
108 } |
97 } |
109 } |