TestLargePageUseForAuxMemory.java revision 10867:5469b15d97f4
1/*
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/*
25 * @test TestLargePageUseForAuxMemory.java
26 * @summary Test that auxiliary data structures are allocated using large pages if available.
27 * @bug 8058354 8079208
28 * @key gc
29 * @library /testlibrary /test/lib
30 * @requires (vm.gc=="G1" | vm.gc=="null")
31 * @build jdk.test.lib.* sun.hotspot.WhiteBox
32 * @build TestLargePageUseForAuxMemory
33 * @run main ClassFileInstaller sun.hotspot.WhiteBox
34 *                              sun.hotspot.WhiteBox$WhiteBoxPermission
35 * @run main/othervm -Xbootclasspath/a:. -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:+IgnoreUnrecognizedVMOptions -XX:+UseLargePages TestLargePageUseForAuxMemory
36 */
37
38import java.lang.Math;
39import java.lang.reflect.InvocationTargetException;
40import java.lang.reflect.Method;
41
42import jdk.test.lib.*;
43import jdk.test.lib.Asserts;
44import sun.hotspot.WhiteBox;
45
46public class TestLargePageUseForAuxMemory {
47    static final long HEAP_REGION_SIZE = 1 * 1024 * 1024;
48    static long largePageSize;
49    static long smallPageSize;
50    static long allocGranularity;
51
52    static void checkSize(OutputAnalyzer output, long expectedSize, String pattern) {
53        String pageSizeStr = output.firstMatch(pattern, 1);
54
55        if (pageSizeStr == null) {
56            output.reportDiagnosticSummary();
57            throw new RuntimeException("Match from '" + pattern + "' got 'null' expected: " + expectedSize);
58        }
59
60        long size = parseMemoryString(pageSizeStr);
61        if (size != expectedSize) {
62            output.reportDiagnosticSummary();
63            throw new RuntimeException("Match from '" + pattern + "' got " + size + " expected: " + expectedSize);
64        }
65    }
66
67    static void checkSmallTables(OutputAnalyzer output, long expectedPageSize) throws Exception {
68        checkSize(output, expectedPageSize, "Block Offset Table: .*page_size=([^ ]+)");
69        checkSize(output, expectedPageSize, "Card Counts Table: .*page_size=([^ ]+)");
70    }
71
72    static void checkBitmaps(OutputAnalyzer output, long expectedPageSize) throws Exception {
73        checkSize(output, expectedPageSize, "Prev Bitmap: .*page_size=([^ ]+)");
74        checkSize(output, expectedPageSize, "Next Bitmap: .*page_size=([^ ]+)");
75    }
76
77    static void testVM(String what, long heapsize, boolean cardsShouldUseLargePages, boolean bitmapShouldUseLargePages) throws Exception {
78        System.out.println(what + " heapsize " + heapsize + " card table should use large pages " + cardsShouldUseLargePages + " " +
79                           "bitmaps should use large pages " + bitmapShouldUseLargePages);
80        ProcessBuilder pb;
81        // Test with large page enabled.
82        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
83                                                   "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE,
84                                                   "-Xms" + heapsize,
85                                                   "-Xmx" + heapsize,
86                                                   "-Xlog:pagesize",
87                                                   "-XX:+UseLargePages",
88                                                   "-XX:+IgnoreUnrecognizedVMOptions",  // there is no ObjectAlignmentInBytes in 32 bit builds
89                                                   "-XX:ObjectAlignmentInBytes=8",
90                                                   "-version");
91
92        OutputAnalyzer output = new OutputAnalyzer(pb.start());
93        checkSmallTables(output, (cardsShouldUseLargePages ? largePageSize : smallPageSize));
94        checkBitmaps(output, (bitmapShouldUseLargePages ? largePageSize : smallPageSize));
95        output.shouldHaveExitValue(0);
96
97        // Test with large page disabled.
98        pb = ProcessTools.createJavaProcessBuilder("-XX:+UseG1GC",
99                                                   "-XX:G1HeapRegionSize=" + HEAP_REGION_SIZE,
100                                                   "-Xms" + heapsize,
101                                                   "-Xmx" + heapsize,
102                                                   "-Xlog:pagesize",
103                                                   "-XX:-UseLargePages",
104                                                   "-XX:+IgnoreUnrecognizedVMOptions",  // there is no ObjectAlignmentInBytes in 32 bit builds
105                                                   "-XX:ObjectAlignmentInBytes=8",
106                                                   "-version");
107
108        output = new OutputAnalyzer(pb.start());
109        checkSmallTables(output, smallPageSize);
110        checkBitmaps(output, smallPageSize);
111        output.shouldHaveExitValue(0);
112    }
113
114    private static long gcd(long x, long y) {
115        while (x > 0) {
116            long t = x;
117            x = y % x;
118            y = t;
119        }
120        return y;
121    }
122
123    private static long lcm(long x, long y) {
124        return x * (y / gcd(x, y));
125    }
126
127    public static void main(String[] args) throws Exception {
128        // Size that a single card covers.
129        final int cardSize = 512;
130        WhiteBox wb = WhiteBox.getWhiteBox();
131        smallPageSize = wb.getVMPageSize();
132        largePageSize = wb.getVMLargePageSize();
133        allocGranularity = wb.getVMAllocationGranularity();
134        final long heapAlignment = lcm(cardSize * smallPageSize, largePageSize);
135
136        if (largePageSize == 0) {
137            System.out.println("Skip tests because large page support does not seem to be available on this platform.");
138            return;
139        }
140        if (largePageSize == smallPageSize) {
141            System.out.println("Skip tests because large page support does not seem to be available on this platform." +
142                               "Small and large page size are the same.");
143            return;
144        }
145
146        // To get large pages for the card table etc. we need at least a 1G heap (with 4k page size).
147        // 32 bit systems will have problems reserving such an amount of contiguous space, so skip the
148        // test there.
149        if (!Platform.is32bit()) {
150            final long heapSizeForCardTableUsingLargePages = largePageSize * cardSize;
151            final long heapSizeDiffForCardTable = Math.max(Math.max(allocGranularity * cardSize, HEAP_REGION_SIZE), largePageSize);
152
153            Asserts.assertGT(heapSizeForCardTableUsingLargePages, heapSizeDiffForCardTable,
154                             "To test we would require to use an invalid heap size");
155            testVM("case1: card table and bitmap use large pages (barely)", heapSizeForCardTableUsingLargePages, true, true);
156            testVM("case2: card table and bitmap use large pages (extra slack)", heapSizeForCardTableUsingLargePages + heapSizeDiffForCardTable, true, true);
157            testVM("case3: only bitmap uses large pages (barely not)", heapSizeForCardTableUsingLargePages - heapSizeDiffForCardTable, false, true);
158        }
159
160        // Minimum heap requirement to get large pages for bitmaps is 128M heap. This seems okay to test
161        // everywhere.
162        final int bitmapTranslationFactor = 8 * 8; // ObjectAlignmentInBytes * BitsPerByte
163        final long heapSizeForBitmapUsingLargePages = largePageSize * bitmapTranslationFactor;
164        final long heapSizeDiffForBitmap = Math.max(Math.max(allocGranularity * bitmapTranslationFactor, HEAP_REGION_SIZE),
165                                                    Math.max(largePageSize, heapAlignment));
166
167        Asserts.assertGT(heapSizeForBitmapUsingLargePages, heapSizeDiffForBitmap,
168                         "To test we would require to use an invalid heap size");
169
170        testVM("case4: only bitmap uses large pages (barely)", heapSizeForBitmapUsingLargePages, false, true);
171        testVM("case5: only bitmap uses large pages (extra slack)", heapSizeForBitmapUsingLargePages + heapSizeDiffForBitmap, false, true);
172        testVM("case6: nothing uses large pages (barely not)", heapSizeForBitmapUsingLargePages - heapSizeDiffForBitmap, false, false);
173    }
174
175    public static long parseMemoryString(String value) {
176        long multiplier = 1;
177
178        if (value.endsWith("B")) {
179            multiplier = 1;
180        } else if (value.endsWith("K")) {
181            multiplier = 1024;
182        } else if (value.endsWith("M")) {
183            multiplier = 1024 * 1024;
184        } else if (value.endsWith("G")) {
185            multiplier = 1024 * 1024 * 1024;
186        } else {
187            throw new IllegalArgumentException("Expected memory string '" + value + "'to end with either of: B, K, M, G");
188        }
189
190        long longValue = Long.parseUnsignedLong(value.substring(0, value.length() - 1));
191
192        return longValue * multiplier;
193    }
194}
195