2023-10-27 06:55:25 +00:00
/ *
2024-02-07 14:54:51 +00:00
* Copyright ( c ) 2023 , 2024 , Oracle and / or its affiliates . All rights reserved .
* Copyright ( c ) 2023 , 2024 , Red Hat Inc .
2023-10-27 06:55:25 +00:00
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER .
*
* This code is free software ; you can redistribute it and / or modify it
* under the terms of the GNU General Public License version 2 only , as
* published by the Free Software Foundation .
*
* This code is distributed in the hope that it will be useful , but WITHOUT
* ANY WARRANTY ; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE . See the GNU General Public License
* version 2 for more details ( a copy is included in the LICENSE file that
* accompanied this code ) .
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work ; if not , write to the Free Software Foundation ,
* Inc . , 51 Franklin St , Fifth Floor , Boston , MA 02110 - 1301 USA .
*
* Please contact Oracle , 500 Oracle Parkway , Redwood Shores , CA 94065 USA
* or visit www . oracle . com if you need additional information or have any
* questions .
* /
/ *
* @test id = Default
* @summary Test JVM large page setup ( default options )
* @library / test / lib
* @requires os . family = = " linux "
* @modules java . base / jdk . internal . misc
* java . management
* @run driver TestHugePageDecisionsAtVMStartup
* /
/ *
* @test id = LP_enabled
* @summary Test JVM large page setup ( + LP )
* @library / test / lib
* @requires os . family = = " linux "
* @modules java . base / jdk . internal . misc
* java . management
* @run driver TestHugePageDecisionsAtVMStartup - XX : + UseLargePages
* /
/ *
* @test id = THP_enabled
* @summary Test JVM large page setup ( + THP )
* @library / test / lib
* @requires os . family = = " linux "
* @modules java . base / jdk . internal . misc
* java . management
* @run driver TestHugePageDecisionsAtVMStartup - XX : + UseTransparentHugePages
* /
import jdk.test.lib.process.OutputAnalyzer ;
import jdk.test.lib.process.ProcessTools ;
import java.util.ArrayList ;
import java.util.Arrays ;
import java.util.List ;
import java.util.Set ;
public class TestHugePageDecisionsAtVMStartup {
// End user warnings, printing with Xlog:pagesize at warning level, should be unconditional
static final String warningNoTHP = " [warning][pagesize] UseTransparentHugePages disabled, transparent huge pages are not supported by the operating system. " ;
static final String warningNoLP = " [warning][pagesize] UseLargePages disabled, no large pages configured and available on the system. " ;
static final String buildSizeString ( long l ) {
String units [ ] = { " K " , " M " , " G " } ;
long factor = 1024 * 1024 * 1024 ;
for ( int i = 2 ; i > = 0 ; i - - ) {
if ( l > = factor ) {
return Long . toString ( l / factor ) + units [ i ] ;
}
factor / = 1024 ;
}
return Long . toString ( l ) + " B " ;
}
static void testOutput ( boolean useLP , boolean useTHP , OutputAnalyzer out , HugePageConfiguration configuration ) {
// Note: If something goes wrong, the JVM warns but continues, so we should never see an exit value != 0
out . shouldHaveExitValue ( 0 ) ;
2024-02-07 14:54:51 +00:00
// Explicit hugepages:
2023-10-27 06:55:25 +00:00
// Let X = the default hugepage size of the system (the one in /proc/meminfo).
// The JVM will cycle through page sizes, starting at X, down to the smallest hugepage size.
//
// Example 1: a system with 1GB and 2MB pages, the default hugepage size is 1GB (can only be done
// via kernel parameter). the JVM should first attempt to use 1GB pages, failing that should try 2MB, failing
// that give up and disable -UseLargePages.
//
// Example 1: same system, but the default hugepage size is 2MB. The JVM should not attempt to use 1GB pages.
//
// This picture gets more complex with -XX:LargePageSizeInBytes, which overrides the default
// large page size; but we ignore this for now (feel free to extend the test to cover LBSiB too).
2024-02-07 14:54:51 +00:00
boolean haveUsableExplicitHugePages = false ;
if ( configuration . supportsExplicitHugePages ( ) ) {
long defaultLargePageSize = configuration . getExplicitDefaultHugePageSize ( ) ;
Set < HugePageConfiguration . ExplicitHugePageConfig > configs = configuration . getExplicitHugePageConfigurations ( ) ;
for ( HugePageConfiguration . ExplicitHugePageConfig config : configs ) {
2023-10-27 06:55:25 +00:00
if ( config . pageSize < = defaultLargePageSize ) {
if ( config . nr_hugepages > 0 | | config . nr_overcommit_hugepages > 0 ) {
2024-02-07 14:54:51 +00:00
haveUsableExplicitHugePages = true ; break ;
2023-10-27 06:55:25 +00:00
}
}
}
}
if ( useTHP & & ! useLP ) {
useLP = true ; // its implicit
}
if ( ! useLP ) {
out . shouldContain ( " [info][pagesize] Large page support disabled " ) ;
} else if ( useLP & & ! useTHP & &
2024-02-07 14:54:51 +00:00
( ! configuration . supportsExplicitHugePages ( ) | | ! haveUsableExplicitHugePages ) ) {
2023-10-27 06:55:25 +00:00
out . shouldContain ( warningNoLP ) ;
} else if ( useLP & & useTHP & & ! configuration . supportsTHP ( ) ) {
out . shouldContain ( warningNoTHP ) ;
} else if ( useLP & & ! useTHP & &
2024-02-07 14:54:51 +00:00
configuration . supportsExplicitHugePages ( ) & & haveUsableExplicitHugePages ) {
out . shouldContain ( " [info][pagesize] Using the default large page size: " + buildSizeString ( configuration . getExplicitDefaultHugePageSize ( ) ) ) ;
2023-10-27 06:55:25 +00:00
out . shouldContain ( " [info][pagesize] UseLargePages=1, UseTransparentHugePages=0 " ) ;
out . shouldContain ( " [info][pagesize] Large page support enabled " ) ;
} else if ( useLP & & useTHP & & configuration . supportsTHP ( ) ) {
2024-02-15 16:01:18 +00:00
long thpPageSize = configuration . getThpPageSizeOrFallback ( ) ;
String thpPageSizeString = buildSizeString ( thpPageSize ) ;
2023-10-27 06:55:25 +00:00
// We expect to see exactly two "Usable page sizes" : the system page size and the THP page size. The system
// page size differs, but its always in KB).
out . shouldContain ( " [info][pagesize] UseLargePages=1, UseTransparentHugePages=1 " ) ;
out . shouldMatch ( " .* \\ [info] \\ [pagesize] Large page support enabled. Usable page sizes: \\ d+[kK], " + thpPageSizeString + " . Default large page size: " + thpPageSizeString + " .* " ) ;
}
}
public static void main ( String [ ] extraOptions ) throws Exception {
List < String > allOptions = new ArrayList < String > ( ) ;
if ( extraOptions ! = null ) {
allOptions . addAll ( Arrays . asList ( extraOptions ) ) ;
}
allOptions . add ( " -Xmx128m " ) ;
allOptions . add ( " -Xlog:pagesize " ) ;
allOptions . add ( " -version " ) ;
boolean useLP = allOptions . contains ( " -XX:+UseLargePages " ) ;
boolean useTHP = allOptions . contains ( " -XX:+UseTransparentHugePages " ) ;
System . out . println ( " useLP: " + useLP + " useTHP: " + useTHP ) ;
2023-10-27 09:51:22 +00:00
ProcessBuilder pb = ProcessTools . createLimitedTestJavaProcessBuilder ( allOptions . toArray ( new String [ 0 ] ) ) ;
2023-10-27 06:55:25 +00:00
OutputAnalyzer output = new OutputAnalyzer ( pb . start ( ) ) ;
output . reportDiagnosticSummary ( ) ;
HugePageConfiguration configuration = HugePageConfiguration . readFromOS ( ) ;
System . out . println ( " configuration read from OS: " + configuration ) ;
testOutput ( useLP , useTHP , output , configuration ) ;
}
}