Что именно делает -XX: -TieredCompilation?
Используя java -XX:+PrintFlagsFinal
, я нашел флаг TieredCompilation
, и я немного об этом прочитал.
Тем не менее, я до сих пор не знаю точно, что произойдет, установив его на false
.
Я знаю, что система компиляции поддерживает 5 уровней выполнения, в основном разделенных на интерпретатор, C1 и C2:
- уровень 0 - интерпретатор
- уровень 1 - C1 с полной оптимизацией (без профилирования)
- уровень 2 - C1 с счетчиками invocation и backedge
- уровень 3 - C1 с полным профилированием (уровень 2 + MDO)
- уровень 4 - C2
Источник: http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/2b2511bd3cc8/src/share/vm/runtime/advancedThresholdPolicy.hpp#l34
Два вопроса:
(1) Установив -XX:-TieredCompilation
, некоторые из этих уровней просто отключены? Если да, то какой?
(2) Есть ли какой-то флаг, чтобы решить, следует ли отключать C1 или C2 или вообще не компилироваться?
Ответы
Ответ 1
-XX:-TieredCompilation
отключает промежуточные уровни компиляции (1, 2, 3), так что метод либо интерпретируется, либо компилируется на максимальном уровне оптимизации (C2).
В качестве побочного эффекта флаг TieredCompilation
также изменяет количество потоков компилятора, политику компиляции и размер кеша кода по умолчанию. Обратите внимание, что при TieredCompilation
отключен
- будет меньше потоков компилятора;
- простая политика компиляции (на основе методов invocation и backedge counters) будет выбрана вместо расширенной политики компиляции;
- Размер зарезервированного кеша по умолчанию будет в 5 раз меньше.
Чтобы отключить компилятор C2 и оставить только C1 без дополнительных накладных расходов, установите -XX:TieredStopAtLevel=1
.
Чтобы отключить все компиляторы JIT и запустить все в интерпретаторе, используйте -Xint
.
Ответ 2
Существуют разные уровни JIT, как вы заметили (в том числе не запуская JIT).
В более ранних версиях Java вам сначала нужно было выбрать их (например, -Xint
, -client
, -server
) для запуска с помощью только интерпретатора с помощью только компилятора клиента (C1) или просто сервер (C2).
Многоуровневая компиляция, которая появилась в Java 7, означала, что компилятор hotspot может легко переключаться между этими шагами. Так что случается, что после определенного количества прогонов код будет скомпилирован с помощью C1, а затем после большего количества запусков он будет скомпилирован с C2. Это выполняется по принципу "по принципу", поэтому, когда приложение работает, значительная часть будет работать только под интерпретатором (для холодного кода), а затем после того, как код будет запущен много (горячий), тогда он будет скомпилирован быть более совершенным. Вы можете видеть разные уровни, запустив
$ java -XX:+PrintFlagsFinal -version | grep CompileThreshold
intx Tier2CompileThreshold = 0
intx Tier3CompileThreshold = 2000
intx Tier4CompileThreshold = 15000
openjdk version "1.8.0_92"
OpenJDK Runtime Environment (Zulu 8.15.0.1-macosx) (build 1.8.0_92-b15)
OpenJDK 64-Bit Server VM (Zulu 8.15.0.1-macosx) (build 25.92-b15, mixed mode)
-XX:-TieredCompilation
по существу TieredCompilation=false
, что означает, что этот переход не выполняется, и вам нужно выбрать фронт, использовать ли клиентский или серверный компилятор. JVM эвристически решает, какой режим применять на основе вашего процессора; если у вас несколько процессоров или 64-разрядная виртуальная машина, то он будет использовать VM сервера (C2), иначе он будет использовать клиентскую VM (C1).
Итак, -Xint
будет работать только с интерпретатором (т.е. без компилятора), и вы можете выбрать только C1 или C2 с -client
или -server
соответственно, вместе с -XX:-TieredCompilation