Skip to content

Commit e60e882

Browse files
author
Afshin Zafari
committed
8335167: Test runtime/Thread/TestAlwaysPreTouchStacks.java failed with Expected a higher ratio between stack committed and reserved
Reviewed-by: stuefe, dholmes, gziemski
1 parent 9176f68 commit e60e882

File tree

2 files changed

+88
-90
lines changed

2 files changed

+88
-90
lines changed

test/hotspot/jtreg/ProblemList.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64
116116
runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64
117117
runtime/StackGuardPages/TestStackGuardPagesNative.java 8303612 linux-all
118118
runtime/ErrorHandling/MachCodeFramesInErrorFile.java 8313315 linux-ppc64le
119-
runtime/Thread/TestAlwaysPreTouchStacks.java 8335167 macosx-aarch64
120119
runtime/cds/appcds/customLoader/HelloCustom_JFR.java 8241075 linux-all,windows-x64
121120

122121
applications/jcstress/copy.java 8229852 linux-all

test/hotspot/jtreg/runtime/Thread/TestAlwaysPreTouchStacks.java

Lines changed: 88 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
import static jdk.test.lib.Platform.isWindows;
3737

3838
/*
39-
* @test id=preTouch
39+
* @test id=preTouchTest
4040
* @summary Test AlwaysPreTouchThreadStacks
4141
* @requires os.family != "aix"
4242
* @library /test/lib
@@ -45,23 +45,16 @@
4545
* @run driver TestAlwaysPreTouchStacks preTouch
4646
*/
4747

48-
/*
49-
* @test id=noPreTouch
50-
* @summary Test that only touched committed memory is reported as thread stack usage.
51-
* @requires os.family != "aix"
52-
* @library /test/lib
53-
* @modules java.base/jdk.internal.misc
54-
* java.management
55-
* @run driver TestAlwaysPreTouchStacks noPreTouch
56-
*/
57-
5848
public class TestAlwaysPreTouchStacks {
5949

6050
// We will create a bunch of large-stacked threads to make a significant imprint on combined thread stack size
61-
final static int MB = 1024*1024;
51+
final static int MB = 1024 * 1024;
6252
static int memoryCeilingMB = 128;
6353
static int threadStackSizeMB = 8;
6454
static int numThreads = memoryCeilingMB / threadStackSizeMB;
55+
static long min_stack_usage_with_pretouch = 1 * MB;
56+
static long max_stack_usage_with_pretouch = (long)(0.75 * threadStackSizeMB * MB);
57+
6558
static CyclicBarrier gate = new CyclicBarrier(numThreads + 1);
6659

6760
static private final Thread createTestThread(int num) {
@@ -79,10 +72,76 @@ static private final Thread createTestThread(int num) {
7972
}
8073
},
8174
"TestThread-" + num, threadStackSizeMB * MB);
75+
// Let test threads run as daemons to ensure that they are still running and
76+
// that their stacks are still allocated when the JVM shuts down and the final
77+
// NMT report is printed.
8278
t.setDaemon(true);
8379
return t;
8480
}
8581

82+
private static long runPreTouchTest(boolean preTouch) throws Exception {
83+
long reserved = 0L, committed = 0L;
84+
ArrayList<String> vmArgs = new ArrayList<>();
85+
Collections.addAll(vmArgs,
86+
"-XX:+UnlockDiagnosticVMOptions",
87+
"-Xmx100M",
88+
"-XX:NativeMemoryTracking=summary", "-XX:+PrintNMTStatistics");
89+
if (preTouch){
90+
vmArgs.add("-XX:+AlwaysPreTouchStacks");
91+
}
92+
if (System.getProperty("os.name").contains("Linux")) {
93+
vmArgs.add("-XX:-UseMadvPopulateWrite");
94+
}
95+
Collections.addAll(vmArgs, "TestAlwaysPreTouchStacks", "test");
96+
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(vmArgs);
97+
OutputAnalyzer output = new OutputAnalyzer(pb.start());
98+
99+
output.shouldHaveExitValue(0);
100+
101+
for (int i = 0; i < numThreads; i++) {
102+
output.shouldContain("Alive: " + i);
103+
}
104+
105+
// If using -XX:+AlwaysPreTouchStacks, we want to see, in the final NMT printout,
106+
// a committed thread stack size very close to reserved stack size. Like this:
107+
// - Thread (reserved=10332400KB, committed=10284360KB)
108+
// (thread #10021)
109+
// (stack: reserved=10301560KB, committed=10253520KB) <<<<
110+
//
111+
// ... without -XX:+AlwaysPreTouchStacks, the committed/reserved ratio for thread stacks should be
112+
// a lot lower, e.g.:
113+
// - Thread (reserved=10332400KB, committed=331828KB)
114+
// (thread #10021)
115+
// (stack: reserved=10301560KB, committed=300988KB) <<<
116+
117+
output.shouldMatch("- *Thread.*reserved.*committed");
118+
output.reportDiagnosticSummary();
119+
Pattern pat = Pattern.compile(".*stack: reserved=(\\d+), committed=(\\d+).*");
120+
boolean foundLine = false;
121+
for (String line : output.asLines()) {
122+
Matcher m = pat.matcher(line);
123+
if (m.matches()) {
124+
reserved = Long.parseLong(m.group(1));
125+
committed = Long.parseLong(m.group(2));
126+
System.out.println(">>>>> " + line + ": " + reserved + " - " + committed);
127+
// Added sanity tests: we expect our test threads to be still alive when NMT prints its final
128+
// report, so their stacks should dominate the NMT-reported total stack size.
129+
long max_reserved = memoryCeilingMB * 3 * MB;
130+
long min_reserved = memoryCeilingMB * MB;
131+
if (reserved >= max_reserved || reserved < min_reserved) {
132+
throw new RuntimeException("Total reserved stack sizes outside of our expectations (" + reserved +
133+
", expected " + min_reserved + ".." + max_reserved + ")");
134+
}
135+
foundLine = true;
136+
break;
137+
}
138+
}
139+
if (!foundLine) {
140+
throw new RuntimeException("Did not find expected NMT output");
141+
}
142+
return committed;
143+
}
144+
86145
public static void main(String[] args) throws Exception {
87146

88147
if (args.length == 1 && args[0].equals("test")) {
@@ -103,83 +162,23 @@ public static void main(String[] args) throws Exception {
103162
// should show up with fully - or almost fully - committed thread stacks.
104163

105164
} else {
106-
boolean preTouch;
107-
if (args.length == 1 && args[0].equals("noPreTouch")){
108-
preTouch = false;
109-
} else if (args.length == 1 && args[0].equals("preTouch")){
110-
preTouch = true;
111-
} else {
112-
throw new RuntimeException("Invalid test input. Must be 'preTouch' or 'noPreTouch'.");
113-
}
114-
ArrayList<String> vmArgs = new ArrayList<>();
115-
Collections.addAll(vmArgs,
116-
"-XX:+UnlockDiagnosticVMOptions",
117-
"-Xmx100M",
118-
"-XX:NativeMemoryTracking=summary", "-XX:+PrintNMTStatistics");
119-
if (preTouch){
120-
vmArgs.add("-XX:+AlwaysPreTouchStacks");
121-
}
122-
if (System.getProperty("os.name").contains("Linux")) {
123-
vmArgs.add("-XX:-UseMadvPopulateWrite");
124-
}
125-
Collections.addAll(vmArgs, "TestAlwaysPreTouchStacks", "test");
126-
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(vmArgs);
127-
OutputAnalyzer output = new OutputAnalyzer(pb.start());
128-
output.reportDiagnosticSummary();
129-
130-
output.shouldHaveExitValue(0);
131-
132-
for (int i = 0; i < numThreads; i++) {
133-
output.shouldContain("Alive: " + i);
134-
}
135-
136-
// If using -XX:+AlwaysPreTouchStacks, we want to see, in the final NMT printout,
137-
// a committed thread stack size very close to reserved stack size. Like this:
138-
// - Thread (reserved=10332400KB, committed=10284360KB)
139-
// (thread #10021)
140-
// (stack: reserved=10301560KB, committed=10253520KB) <<<<
141-
//
142-
// ... without -XX:+AlwaysPreTouchStacks, the committed/reserved ratio for thread stacks should be
143-
// a lot lower, e.g.:
144-
// - Thread (reserved=10332400KB, committed=331828KB)
145-
// (thread #10021)
146-
// (stack: reserved=10301560KB, committed=300988KB) <<<
147-
148-
output.shouldMatch("- *Thread.*reserved.*committed");
149-
Pattern pat = Pattern.compile(".*stack: reserved=(\\d+), committed=(\\d+).*");
150-
boolean foundLine = false;
151-
for (String line : output.asLines()) {
152-
Matcher m = pat.matcher(line);
153-
if (m.matches()) {
154-
long reserved = Long.parseLong(m.group(1));
155-
long committed = Long.parseLong(m.group(2));
156-
System.out.println(">>>>> " + line + ": " + reserved + " - " + committed);
157-
// This is a bit fuzzy: even with PreTouch we don't commit the full range of what NMT counts
158-
// as thread stack. But without pre-touching, the thread stacks would be committed to about 1/5th
159-
// of their reserved size. Requiring them to be committed for over 3/4th shows that pretouch is
160-
// really working.
161-
if (preTouch && (double)committed < ((double)reserved * 0.75)) {
162-
throw new RuntimeException("Expected a higher ratio between stack committed and reserved.");
163-
} else if (!preTouch && (double)committed > ((double)reserved * 0.50)){
164-
throw new RuntimeException("Expected a lower ratio between stack committed and reserved.");
165-
}
166-
// Added sanity tests: we expect our test threads to be still alive when NMT prints its final
167-
// report, so their stacks should dominate the NMT-reported total stack size.
168-
long max_reserved = memoryCeilingMB * 3 * MB;
169-
long min_reserved = memoryCeilingMB * MB;
170-
if (reserved >= max_reserved || reserved < min_reserved) {
171-
throw new RuntimeException("Total reserved stack sizes outside of our expectations (" + reserved +
172-
", expected " + min_reserved + ".." + max_reserved + ")");
173-
}
174-
foundLine = true;
175-
break;
176-
}
177-
}
178-
if (!foundLine) {
179-
throw new RuntimeException("Did not find expected NMT output");
180-
}
181-
}
182-
165+
long pretouch_committed = runPreTouchTest(true);
166+
long no_pretouch_committed = runPreTouchTest(false);
167+
if (pretouch_committed == 0 || no_pretouch_committed == 0) {
168+
throw new RuntimeException("Could not run with PreTouch flag.");
169+
}
170+
long expected_delta = numThreads * (max_stack_usage_with_pretouch - min_stack_usage_with_pretouch);
171+
long actual_delta = pretouch_committed - no_pretouch_committed;
172+
if (pretouch_committed <= (no_pretouch_committed + expected_delta)) {
173+
throw new RuntimeException("Expected a higher amount of committed with pretouch stacks" +
174+
"PreTouch amount: " + pretouch_committed +
175+
"NoPreTouch amount: " + (no_pretouch_committed + expected_delta));
176+
}
177+
if (actual_delta < expected_delta) {
178+
throw new RuntimeException("Expected a higher delta between stack committed of with and without pretouch." +
179+
"Expected: " + expected_delta + " Actual: " + actual_delta);
180+
}
181+
}
183182
}
184183

185184
}

0 commit comments

Comments
 (0)