Новые оптимизации компилятора VM. Часть 3: Многоуровневая компиляция Как известно, в версиях HotSpot до 1.5 включительно существовало два динамических компилятора—клиентский (client) и серверный (server). Такое разделение—компромисс между двумя крайностями: режимом полной интерпретации (-Xint; маленькая скрость выполенения) и режимом полной предварительной компиляции кода (-Xcomp; большая задержка при запуске). Первый компиялятор работает быстрее, но генерирует менее оптимизированный код, и в результате более подходит для коротких приложений, например апплетов, где скорость запуска критична. В противоположность этому, серверный компилятор хорошо подходит для приложений, выполняющихся долго (например, web-сервер), где скоростью запуска можно пренебречь, но важно добиться быстродействия кода.
Java HotSpot 1.6 делает первые шаги по соединию обоих компиляторов в одно целое. Конечным результатом должно стать устранение необходимости в опциях командной строки -client и -server, выбирающих компилятор при запуске приложения. При этом сначала будет использоваться клиентский компилятор для того, чтобы обеспечить быстрый запуск, а затем, по мере работы приложения, наиболее часто вызываемые методы будут компилироваться с помощью серверного компилятора.
При решении данной задачи были две основные проблемы: разные конвенции вызова (метод, скомпилированный клиентским компилятором, не мог вызывать метод, созданный серверным компилятором и наоборот) и разные интерфейсы времени выполнения. Каждый из компиляторов имел различные конвенции вызовов. В HotSpot 1.6 существует единое соглашение о сопоставлении регистров и слотов стека (stack slots), используемых для передачи параметров и возврата результата сигнатуре метода. В итоге методы, созданные разными компиляторами, теперь могут вызывать друг друга.
Со второй проблемой было
немого сложнее. Во-первых, различалась реализация адаптеров перехода
от интерпретированного кода к скомпилированному
(interpreter-to-compiled, i2c) и наоборот (c2i). Серверный компилятор
создавал адаптеры как отдельные участки кода—для каждой
сигнатуры был свой адаптер, и делалось это в специальном потоке.
Клиентский компилятор встраивал c2i-адаптеры прямо в код
скомпилированного метода. В HotSpot 1.6 используется общий код для
генерации адаптеров. В итоге—уменьшение размера кода по
сравнению с клиентским компилятором, а также уменьшение количества внутренних потоков в JVM.
Во-вторых, каждый компилятор имел свое соглашение о вызове native-методов. Переход от метода Java к native и возврат из него требуют хорошо сформулированной последовательности изменения состояний потока. Код, используемый в клиентском компиляторе, был достаточно прямолинейным и легко сопровождаемым. Аналогичный процедура в серверном компиляторе была очень трудна для понимания и сопровождения. В HotSpot 1.6 теперь используется общий код.
Есть еще задачи, которые необходимо решить для объединения компиляторов. Прежде всего—это написание общего кода для остальных видов адаптеров, используемых, например, при деоптимизации и обработке исключений. Кроме того, необходимо продумать и реализовать различные стратегии, например, в какой момент необходимо деоптимизировать метод и когда собирать информацию для профилирования. Наконец, клиентский компилятор должен поддерживать 64-битные платформы.
Таким образом, можно ожидать значительного увеличения производительности виртуальной машины Java HotSpot. Кроме завершения многоуровневой компиляции планируется использовать результаты escape-анализа, а также уменьшить стоимость вызовов native-методов через интерфейс JNI.
Предположительно, все эти улучшения будут осуществлены в HotSpot 1.7.
Игорь Привалов


Из статьи, к сожалению, непонятно за счёт чего будет достигнут прирост производительности, например, для серверного компилятора. Насколько я могу судить, он и так использует наиболее агрессивные стратегии компиляции, а объединение его с клиентским компилятором вряд ли пойдёт ему на пользу.
опубликовал Дмитрий Май 25, 2008 at 05:44 PM MSD #