Spec-Zone .ru
спецификации, руководства, описания, API
|
Разделенная на уровни компиляция, представленная в Java SE 7, приносит клиентские скорости запуска к серверу VM. Обычно, сервер, VM использует интерпретатор, чтобы собрать информацию профилирования о методах, которая питается в компилятор. В разделенной на уровни схеме, в дополнение к интерпретатору, клиентский компилятор используется, чтобы генерировать скомпилированные версии методов, которые собирают информацию профилирования о себе. Так как скомпилированный код существенно быстрее чем интерпретатор, программа выполняется с большей производительностью во время фазы профилирования. Во многих случаях запуск, который еще быстрее чем с клиентом VM, может быть достигнут, потому что заключительный код, произведенный компилятором сервера, может быть уже доступным во время ранних стадий инициализации приложения. Разделенная на уровни схема может также достигнуть лучшей пиковой производительности чем регулярный сервер VM, потому что более быстрая фаза профилирования позволяет более длительный период профилирования, которое может привести к лучшей оптимизации.
Чтобы работать с разделенной на уровни компиляцией, пожалуйста, определите -server -XX:+TieredCompilation
. Оба режима на 32 и 64 бита поддерживаются, так же как сжимались ой (см. следующий раздел).
"ООП", или обычный объектный указатель в языке Горячей точки Java, является управляемым указателем к объекту. ООП обычно является тем же самым размером как собственный машинный указатель, что означает 64 бита на системе LP64. На системе ILP32 максимальный размер "кучи" - несколько меньше чем 4 гигабайта, который недостаточен для многих приложений. На системе LP64 "куче", используемой данной программой, возможно, придется быть приблизительно в 1.5 раза больше чем тогда, когда она выполняется на системе ILP32. Это требование происходит из-за расширенного размера управляемых указателей. Память недорога, но в эти дни пропускная способность и кэш в дефиците, так значительно увеличивают размер "кучи" и только добираются только по пределу на 4 гигабайта, нежелательный.
Управляемые указатели в "куче" Java указывают на объекты, которые являются выровненные на 8-байтовых границах адреса. Сжатый ой представляют управляемые указатели (во многих, но не всех местах в программном обеспечении JVM), поскольку 32-разрядный объект смещает от 64-разрядного базового адреса "кучи" Java. Поскольку они - объектные смещения, а не байтовые смещения, они могут использоваться, чтобы адресовать до четырех миллиардов объектов (не байты), или размер "кучи" приблизительно до 32 гигабайтов. Чтобы использовать их, они должны масштабироваться фактором 8 и добавлены к базовому адресу "кучи" Java, чтобы найти объект, к которому они обращаются. Объектные размеры, используя сжатый ой сопоставимы с теми в режиме ILP32.
Термин декодирование используется, чтобы выразить работу, которой 32-разрядное сжатое ООП преобразовывается в 64-разрядный собственный адрес в управляемую "кучу". Обратная работа упоминается как кодирование.
Сжатый ой поддерживается и включается по умолчанию в Java SE 6u23 и позже. В Java SE 7, использование сжатых ООП является значением по умолчанию для 64-разрядных процессов JVM когда -Xmx
не определяется и для значений -Xmx
меньше чем 32 гигабайта. Для JDK 6 перед 6u23 выпуск, используйте -XX:+UseCompressedOops
флаг с java
команда, чтобы активировать опцию.
При использовании сжатых ООП в 64-разрядном процессе виртуальной машины Java программное обеспечение JVM просит, чтобы операционная система зарезервировала память для "кучи" Java, запускающейся в виртуальном нуле адреса. Если операционная система поддерживает такой запрос и может зарезервировать память для "кучи" Java в виртуальном нуле адреса, то основанные на нуле сжатые ООП используются.
Использование основанных на нуле сжатых ООП означает, что 64-разрядный указатель может декодироваться от 32-разрядного объектного смещения, не добавляя в базовом адресе "кучи" Java. Для размеров "кучи" меньше чем 4 гигабайта программное обеспечение JVM может использовать байтовое смещение вместо объектного смещения и таким образом также избежать масштабировать смещение 8. Кодирование 64-разрядного адреса в 32-разрядное смещение соответственно эффективно.
Поскольку Java наваливает размеры приблизительно 26 гигабайтов, любой Солярис, Linux, и операционные системы Windows обычно будут в состоянии выделить "кучу" Java в виртуальном нуле адреса.
Escape-анализ является методом, которым Компилятор Сервера Горячей точки Java может проанализировать контекст использования нового объекта и решить, выделить ли это на "куче" Java.
Escape-анализ поддерживается и включается по умолчанию в Java SE 6u23 и позже.
Компилятор Сервера Горячей точки Java реализует нечувствительный к потоку алгоритм escape-анализа, описанный в:
[Choi99] Jong-Deok Choi, Manish Gupta, Mauricio Seffano, Vugranam C. Sreedhar, Sam Midkiff, "Escape Analysis for Java", Procedings of ACM SIGPLAN OOPSLA Conference, November 1, 1999
Основанный на escape-анализе, состояние escape объекта могло бы быть одним из следующего:
GlobalEscape
– Объект выходит из метода и потока. Например, объект, хранивший в статическом поле, или, сохраненный в поле оставленного объекта, или, возвратился как результат текущего метода.ArgEscape
– Объект, который передают как параметр или ссылаемый параметром, но, глобально не выходит во время вызова. Это состояние определяется, анализируя байт-код вызванного метода.NoEscape
– Скалярный заменимый объект, означая его выделение мог быть удален из сгенерированного кода.После escape-анализа компилятор сервера устраняет скалярные заменимые объектные выделения и связанные блокировки от сгенерированного кода. Компилятор сервера также устраняет блокировки для всех неглобально объектов выхода. Это не заменяет выделение "кучи" выделением стека для того, чтобы неглобально выйти из объектов.
Некоторые сценарии для escape-анализа описываются затем.
public class Person { private String name; private int age; public Person(String personName, int personAge) { name = personName; age = personAge; } public Person(Person p) { this(p.getName(), p.getAge()); } public int getName() { return name; } public int getAge() { return age; } } public class Employee { private Person person; // makes a defensive copy to protect against modifications by caller public Person getPerson() { return new Person(person) }; public void printEmployeeDetail(Employee emp) { Person person = emp.getPerson(); // this caller does not modify the object, so defensive copy was unnecessary System.out.println ("Employee's name: " + person.getName() + "; age: " + person.getAge()); } }Метод делает копию, чтобы предотвратить модификацию исходного объекта вызывающей стороной. Если компилятор решает что
getPerson
метод вызывается в цикле, он встроит тот метод. Кроме того, посредством escape-анализа, если компилятор решает, что исходный объект никогда не изменяется, он мог бы оптимизировать и устранить вызов, чтобы сделать копию.StringBuffer
и Vector
синхронизируются, потому что к ним могут получить доступ различные потоки. Однако, в большинстве сценариев, они используются в потоке локальный способ. В случаях, где использование является локальным потоком, компилятор мог бы оптимизировать и удалить блоки синхронизации.Параллельный сборщик "мусора" Мусорщика был расширен, чтобы использовать в своих интересах машины с NUMA (Не Универсальный Доступ Памяти) архитектура. Большинство современных компьютеров основано на архитектуре NUMA, в которой требуется различное количество времени, чтобы получить доступ к различным частям памяти. Как правило, у каждого процессора в системе есть локальная память, которая обеспечивает низкую задержку доступа и высокую пропускную способность, и удаленную память, которая значительно медленнее к доступу.
В Java Виртуальная машина HotSpot осведомленное о NUMA средство выделения было реализовано, чтобы использовать в своих интересах такие системы и обеспечить автоматическую оптимизацию размещения памяти для приложений Java. Средство выделения управляет пространством рая молодой генерации "кучи", где большинство новых объектов создается. Средство выделения делит пространство на области, каждая из которых помещается в память определенного узла. Средство выделения полагается на гипотезу, что поток, который выделяет объект, будет наиболее вероятным использовать объект. Чтобы гарантировать самый быстрый доступ к новому объекту, средство выделения помещает это в область, локальную для потока выделения. Области могут быть динамически изменены, чтобы отразить уровень выделения потоков приложения, работающих на различных узлах. Это позволяет увеличить производительность даже однопоточных приложений. Кроме того, "от" и "до" пробелов оставшегося в живых молодой генерации, старой генерации, и постоянной генерации включали страницу, чередующуюся для них. Это гарантирует, что у всех потоков есть равные задержки доступа к этим пробелам в среднем.
Осведомленное о NUMA средство выделения доступно на операционной системе Solaris™, запускающейся в Солярисе 9 12/02 и на Операционной системе Linux, запускающейся в ядре Linux 2.6.19 и glibc 2.6.1.
Осведомленное о NUMA средство выделения может быть включено с -XX:+UseNUMA
флаг в соединении с выбором Параллельного сборщика "мусора" Мусорщика. Параллельный сборщик "мусора" Мусорщика является значением по умолчанию для машины класса сервера. Параллельный сборщик "мусора" Мусорщика может также быть включен явно, определяя -XX:+UseParallelGC
опция.
-XX:+UseNUMA
флаг был добавлен в Java SE 6u2.
Когда оценено против СПЕЦИФИКАЦИИ сравнительный тест JBB 2005 года на машине Opteron с 8 микросхемами, осведомленные о NUMA системы показали следующие увеличения производительности: