8356000: C1/C2-only modes use 2 compiler threads on low CPU count machines
Reviewed-by: kvn, dfenacci, galder
This commit is contained in:
parent
a2723d91df
commit
4e314cb9e0
@ -550,6 +550,7 @@ void CompilationPolicy::initialize() {
|
|||||||
int count = CICompilerCount;
|
int count = CICompilerCount;
|
||||||
bool c1_only = CompilerConfig::is_c1_only();
|
bool c1_only = CompilerConfig::is_c1_only();
|
||||||
bool c2_only = CompilerConfig::is_c2_or_jvmci_compiler_only();
|
bool c2_only = CompilerConfig::is_c2_or_jvmci_compiler_only();
|
||||||
|
int min_count = (c1_only || c2_only) ? 1 : 2;
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
// Turn on ergonomic compiler count selection
|
// Turn on ergonomic compiler count selection
|
||||||
@ -560,7 +561,7 @@ void CompilationPolicy::initialize() {
|
|||||||
// Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n
|
// Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n
|
||||||
int log_cpu = log2i(os::active_processor_count());
|
int log_cpu = log2i(os::active_processor_count());
|
||||||
int loglog_cpu = log2i(MAX2(log_cpu, 1));
|
int loglog_cpu = log2i(MAX2(log_cpu, 1));
|
||||||
count = MAX2(log_cpu * loglog_cpu * 3 / 2, 2);
|
count = MAX2(log_cpu * loglog_cpu * 3 / 2, min_count);
|
||||||
// Make sure there is enough space in the code cache to hold all the compiler buffers
|
// Make sure there is enough space in the code cache to hold all the compiler buffers
|
||||||
size_t c1_size = 0;
|
size_t c1_size = 0;
|
||||||
#ifdef COMPILER1
|
#ifdef COMPILER1
|
||||||
@ -574,7 +575,7 @@ void CompilationPolicy::initialize() {
|
|||||||
int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size;
|
int max_count = (ReservedCodeCacheSize - (CodeCacheMinimumUseSpace DEBUG_ONLY(* 3))) / (int)buffer_size;
|
||||||
if (count > max_count) {
|
if (count > max_count) {
|
||||||
// Lower the compiler count such that all buffers fit into the code cache
|
// Lower the compiler count such that all buffers fit into the code cache
|
||||||
count = MAX2(max_count, c1_only ? 1 : 2);
|
count = MAX2(max_count, min_count);
|
||||||
}
|
}
|
||||||
FLAG_SET_ERGO(CICompilerCount, count);
|
FLAG_SET_ERGO(CICompilerCount, count);
|
||||||
}
|
}
|
||||||
@ -593,9 +594,10 @@ void CompilationPolicy::initialize() {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (c1_only) {
|
if (c1_only) {
|
||||||
// No C2 compiler thread required
|
// No C2 compiler threads are needed
|
||||||
set_c1_count(count);
|
set_c1_count(count);
|
||||||
} else if (c2_only) {
|
} else if (c2_only) {
|
||||||
|
// No C1 compiler threads are needed
|
||||||
set_c2_count(count);
|
set_c2_count(count);
|
||||||
} else {
|
} else {
|
||||||
#if INCLUDE_JVMCI
|
#if INCLUDE_JVMCI
|
||||||
@ -613,6 +615,9 @@ void CompilationPolicy::initialize() {
|
|||||||
}
|
}
|
||||||
assert(count == c1_count() + c2_count(), "inconsistent compiler thread count");
|
assert(count == c1_count() + c2_count(), "inconsistent compiler thread count");
|
||||||
set_increase_threshold_at_ratio();
|
set_increase_threshold_at_ratio();
|
||||||
|
} else {
|
||||||
|
// Interpreter mode creates no compilers
|
||||||
|
FLAG_SET_ERGO(CICompilerCount, 0);
|
||||||
}
|
}
|
||||||
set_start_time(nanos_to_millis(os::javaTimeNanos()));
|
set_start_time(nanos_to_millis(os::javaTimeNanos()));
|
||||||
}
|
}
|
||||||
|
177
test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java
Normal file
177
test/hotspot/jtreg/compiler/arguments/TestCompilerCounts.java
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
/*
|
||||||
|
* Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
|
||||||
|
* 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
|
||||||
|
* @library /test/lib /
|
||||||
|
* @bug 8356000
|
||||||
|
* @requires vm.flagless
|
||||||
|
* @requires vm.bits == "64"
|
||||||
|
* @run driver compiler.arguments.TestCompilerCounts
|
||||||
|
*/
|
||||||
|
|
||||||
|
package compiler.arguments;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import jdk.test.lib.Asserts;
|
||||||
|
import jdk.test.lib.process.ProcessTools;
|
||||||
|
import jdk.test.lib.process.OutputAnalyzer;
|
||||||
|
import jdk.test.lib.cli.CommandLineOptionTest;
|
||||||
|
|
||||||
|
public class TestCompilerCounts {
|
||||||
|
|
||||||
|
// Try not to go over max CPU count on the machine, since we do not
|
||||||
|
// know if the rest of runtime would accept it.
|
||||||
|
// For local testing, feel free to override this to a larger value
|
||||||
|
// if you want to see how heuristics works on even larger machines.
|
||||||
|
static final int MAX_CPUS = Runtime.getRuntime().availableProcessors();
|
||||||
|
|
||||||
|
// Test at most 16 CPUs linearly, to limit test execution time.
|
||||||
|
// After this limit, go for exponential steps.
|
||||||
|
static final int MAX_LINEAR_CPUS = Math.min(16, MAX_CPUS);
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Throwable {
|
||||||
|
// CICompilerCount=0 is incorrect in default modes.
|
||||||
|
fail("-XX:CICompilerCount=0");
|
||||||
|
|
||||||
|
// Interpreter-only mode accepts all values, but sets 0 threads
|
||||||
|
pass(0, "-XX:CICompilerCount=1", "-XX:TieredStopAtLevel=0");
|
||||||
|
|
||||||
|
// C1/C2 only modes accept CICompilerCount=1
|
||||||
|
pass(1, "-XX:CICompilerCount=1", "-XX:TieredStopAtLevel=1");
|
||||||
|
pass(1, "-XX:CICompilerCount=1", "-XX:TieredStopAtLevel=2");
|
||||||
|
pass(1, "-XX:CICompilerCount=1", "-XX:TieredStopAtLevel=3");
|
||||||
|
pass(1, "-XX:CICompilerCount=1", "-XX:-TieredCompilation");
|
||||||
|
|
||||||
|
// C1+C2 modes need at least 2 threads
|
||||||
|
fail("-XX:CICompilerCount=1");
|
||||||
|
fail("-XX:CICompilerCount=1", "-XX:TieredStopAtLevel=4");
|
||||||
|
|
||||||
|
// Overriding the CICompilerCount overrides compiler counts hard.
|
||||||
|
for (int count = 2; count <= MAX_CPUS; count += (count >= MAX_LINEAR_CPUS ? count : 1)) {
|
||||||
|
String opt = "-XX:CICompilerCount=" + count;
|
||||||
|
|
||||||
|
// Interpreter-only mode always sets 0 threads
|
||||||
|
pass(0, opt, "-XX:TieredStopAtLevel=0");
|
||||||
|
|
||||||
|
// All compiled modes accept reasonable CICompilerCount
|
||||||
|
pass(count, opt);
|
||||||
|
pass(count, opt, "-XX:TieredStopAtLevel=1");
|
||||||
|
pass(count, opt, "-XX:TieredStopAtLevel=2");
|
||||||
|
pass(count, opt, "-XX:TieredStopAtLevel=3");
|
||||||
|
pass(count, opt, "-XX:TieredStopAtLevel=4");
|
||||||
|
pass(count, opt, "-XX:-TieredCompilation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per CPU heuristics is disabled, we are going to set up defaults.
|
||||||
|
|
||||||
|
for (int cpus = 2; cpus <= MAX_CPUS; cpus += (cpus >= MAX_LINEAR_CPUS ? cpus : 1)) {
|
||||||
|
String opt = "-XX:ActiveProcessorCount=" + cpus;
|
||||||
|
String opt2 = "-XX:-CICompilerCountPerCPU";
|
||||||
|
|
||||||
|
// Interpreter-only mode always set 0 threads
|
||||||
|
pass(0, opt, opt2, "-XX:TieredStopAtLevel=0");
|
||||||
|
|
||||||
|
// All compiled modes default to 2 threads, statically compiled in
|
||||||
|
pass(2, opt, opt2);
|
||||||
|
pass(2, opt, opt2, "-XX:TieredStopAtLevel=1");
|
||||||
|
pass(2, opt, opt2, "-XX:TieredStopAtLevel=2");
|
||||||
|
pass(2, opt, opt2, "-XX:TieredStopAtLevel=3");
|
||||||
|
pass(2, opt, opt2, "-XX:TieredStopAtLevel=4");
|
||||||
|
pass(2, opt, opt2, "-XX:-TieredCompilation");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we set CICompilerCount heuristically.
|
||||||
|
|
||||||
|
// Check hitting the lower values exactly first.
|
||||||
|
for (int cpus = 1; cpus <= 3; cpus++) {
|
||||||
|
String opt = "-XX:ActiveProcessorCount=" + cpus;
|
||||||
|
|
||||||
|
// Interpreter-only mode always set 0 threads
|
||||||
|
pass(0, opt, "-XX:TieredStopAtLevel=0");
|
||||||
|
|
||||||
|
// Non-tiered modes set 1 thread
|
||||||
|
pass(1, opt, "-XX:TieredStopAtLevel=1");
|
||||||
|
pass(1, opt, "-XX:TieredStopAtLevel=2");
|
||||||
|
pass(1, opt, "-XX:TieredStopAtLevel=3");
|
||||||
|
pass(1, opt, "-XX:-TieredCompilation");
|
||||||
|
|
||||||
|
// Tiered modes set 2 threads
|
||||||
|
pass(2, opt);
|
||||||
|
pass(2, opt, "-XX:TieredStopAtLevel=4");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check what heuristics sets past the trivial number of CPUs.
|
||||||
|
for (int cpus = 4; cpus <= MAX_CPUS; cpus += (cpus >= MAX_LINEAR_CPUS ? cpus : 1)) {
|
||||||
|
String opt = "-XX:ActiveProcessorCount=" + cpus;
|
||||||
|
|
||||||
|
// Interpreter-only mode always set 0 threads
|
||||||
|
pass(0, opt, "-XX:TieredStopAtLevel=0");
|
||||||
|
|
||||||
|
// Non-tiered modes
|
||||||
|
int nonTieredCount = heuristicCount(cpus, false);
|
||||||
|
pass(nonTieredCount, opt, "-XX:TieredStopAtLevel=1");
|
||||||
|
pass(nonTieredCount, opt, "-XX:TieredStopAtLevel=2");
|
||||||
|
pass(nonTieredCount, opt, "-XX:TieredStopAtLevel=3");
|
||||||
|
pass(nonTieredCount, opt, "-XX:-TieredCompilation");
|
||||||
|
|
||||||
|
// Tiered modes
|
||||||
|
int tieredCount = heuristicCount(cpus, true);
|
||||||
|
pass(tieredCount, opt);
|
||||||
|
pass(tieredCount, opt, "-XX:TieredStopAtLevel=4");
|
||||||
|
|
||||||
|
// Also check that heuristics did not set up more threads than CPUs available
|
||||||
|
Asserts.assertTrue(nonTieredCount <= cpus,
|
||||||
|
"Non-tiered count is larger than number of CPUs: " + nonTieredCount + " > " + cpus);
|
||||||
|
Asserts.assertTrue(tieredCount <= cpus,
|
||||||
|
"Tiered count is larger than number of CPUs: " + tieredCount + " > " + cpus);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Direct translation from CompilationPolicy::initialize:
|
||||||
|
public static int heuristicCount(int cpus, boolean tiered) {
|
||||||
|
int log_cpu = log2(cpus);
|
||||||
|
int loglog_cpu = log2(Math.max(log_cpu, 1));
|
||||||
|
int min_count = tiered ? 2 : 1;
|
||||||
|
return Math.max(log_cpu * loglog_cpu * 3 / 2, min_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int log2(int v) {
|
||||||
|
return (int)(Math.log(v) / Math.log(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void pass(int count, String... args) throws Throwable {
|
||||||
|
CommandLineOptionTest.verifyOptionValueForSameVM("CICompilerCount", "" + count, "", args);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void fail(String... args) throws Throwable {
|
||||||
|
ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder(args);
|
||||||
|
OutputAnalyzer output = new OutputAnalyzer(pb.start());
|
||||||
|
output.shouldNotHaveExitValue(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user