2010-07-12 3 views
2

Из того, что я прочитал, java (обычно), похоже, компилирует java не очень (вообще)? Оптимизировал java-байт-код, оставив его в jit для оптимизации. Это правда? И если это было какое-то исследование (возможно, в альтернативных реализациях), чтобы заставить компилятор оптимизировать код, чтобы у jit было меньше работы (возможно ли это)?Вопросы о возможной оптимизации java (или другого языка с управлением памятью)

Кроме того, многие люди, похоже, не любят генерировать собственный код (иногда называемый компиляцией заранее) для Java (и многих других языков управления с высоким уровнем памяти) по многим причинам, таким как потеря переносимости (и ect .), но также частично потому, что (по крайней мере, для тех языков, которые имеют компилятор только во времени), мышление гласит, что компиляция до машинного кода досрочно комментирует возможные оптимизации, которые могут выполняться jit-компилятором и, следовательно, может быть медленнее в долгосрочной перспективе.

Это заставляет меня задаться вопросом, пытался ли кто-либо когда-либо реализовать http://en.wikipedia.org/wiki/Profile-guided_optimization (компиляция в двоичный файл + некоторые дополнительные функции, а затем запуск программы и анализ информации о времени выполнения тестового прогона для создания, по-видимому, более оптимизированного бинарного файла для использования в реальном мире) для java/(других языков, управляемых памятью) и как это будет сравниваться с jit-кодом? Кто-нибудь знает?

ответ

2

Оптимизация с профайлами имеет некоторые оговорки, один из которых упоминается даже в связанной статье Wiki. Реализованы результаты

  • для данных образцов, представляющих, как ваш код фактически используется пользователем или другим кодом.
  • для данной платформы (процессор, память + другое оборудование, ОС, что угодно).
    С точки зрения производительности существуют довольно большие различия даже среди платформ, которые обычно считаются (более или менее) одинаковыми (например, сравнение одного ядра, старого Athlon с 512 М с 6-ядерным процессором Intel с 8G, работающим на Linux, но с очень разными версиями ядра).
  • для данной JVM и ее конфигурации.

Если какое-либо из этих изменений изменилось, то ваши профилирующие результаты (и их оптимизация на основе их) больше не нужны. Скорее всего, некоторые из оптимизаций будут по-прежнему иметь положительный эффект, но некоторые из них могут оказаться неоптимальными (или даже ухудшающими производительность).

Как уже упоминалось, JIT JVM делают что-то очень похожее на профилирование, но они делают это на лету. Он также называется «hotspot», поскольку он постоянно контролирует исполняемый код, ищет горячие точки, которые выполняются часто, и будет пытаться оптимизировать только те части. На этом этапе он сможет использовать больше знаний о коде (зная его контекст, как он используется другими классами и т. Д.), Так что, как упомянуто вами и другими ответами, он может улучшить оптимизацию как статический. Он продолжит мониторинг, и если он понадобится, он сделает еще один поворот оптимизации позже, на этот раз пытаясь еще усерднее (ищет более дорогие оптимизации).
Работа с данными реальной жизни (статистика использования + платформа + конфигурация) позволяет избежать описанных выше предостережений.

Цена на это некоторое дополнительное время, которое необходимо потратить на «профилирование» + JIT-ing. Большую часть времени он проводил довольно хорошо.

Я предполагаю, что профиль наведением оптимизатор все еще может конкурировать с ним (или даже бить его), но только в некоторых особых случаях, если вы можете избежать предостережений:

  • вы совершенно уверены, что ваши образцы хорошо представляют сценарий реальной жизни, и они не будут слишком сильно меняться во время исполнения.
  • Вы точно знаете свою целевую платформу и можете выполнять профилирование на ней.
  • и, конечно же, вы знаете/управляете JVM и его конфигурацией.

Это произойдет редко, и я думаю, что в целом JIT даст вам лучшие результаты, но у меня нет никаких доказательств.

Еще одна возможность получить выгоду от оптимизации с помощью профиля, если вы нацеливаете JVM, которая не может оптимизировать JIT (я думаю, что у большинства небольших устройств есть такая JVM).

К сожалению, одного недостатка, упомянутого в других ответах, было бы очень легко избежать: если статическая/оптимизированная по профилю оптимизация медленна (что, вероятно, так и происходит), то делайте это только для релизов (или RCs, идущих к тестерам) или во время ночных сборок (где время не так важно).
Я думаю, что гораздо большая проблема заключалась бы в том, чтобы иметь хорошие примеры тестов. Создание и поддержание их обычно непросто и занимает много времени. Особенно, если вы хотите, чтобы их можно было выполнить автоматически, что в этом случае было бы очень важно.

4

Лично я считаю, что большая разница заключается не в компиляции JIT и компиляции AOT, а между компиляцией классов и оптимизации всей программы.

При запуске javac он просматривает только один файл .java, скомпилировав его в один файл .class. Все реализации интерфейса и виртуальные методы и переопределения проверяются на достоверность, но остаются нерешенными (потому что невозможно узнать истинные цели вызова метода без анализа всей программы).

JVM использует «загрузку и компоновку времени выполнения», чтобы собрать все ваши классы в последовательную программу (и любой класс в вашей программе может ссылаться на специализированное поведение, чтобы изменить поведение загрузки/привязки по умолчанию).

Но тогда, во время выполнения, JVM может удалить подавляющее большинство виртуальных методов. Он может встроить все ваши геттеры и сеттеры, превращая их в необработанные поля. И когда эти необработанные поля встроены, он может выполнять постоянное распространение для дальнейшей оптимизации кода. (Во время выполнения нет такой вещи, как частное поле.) И если есть только один поток, JVM может устранить все примитивы синхронизации.

Короче говоря, существует множество оптимизаций, которые невозможны без анализа всей программы, и наилучшее время для проведения анализа всей программы - во время выполнения.

+0

Согласен. Обратите внимание, что некоторые AOT-компиляторы (gcc - единственный, о котором я знаю, но могут быть и другие) имеют эту функцию и называем ее «оптимизацией времени соединения». Это относительно новое, хотя и все еще связано с угадыванием, какая функция будет вызываться чаще всего. Хотя в этом есть «оптимизация с учетом профиля», о которой упомянул ОП. – delnan

1

Официальный Java-компилятор Java Hot Spot выполняет «адаптивную оптимизацию» во время выполнения, что по сути совпадает с оптимизацией, управляемой профилем. Это была особенность, по крайней мере, этой конкретной реализации Java в течение длительного времени.

Компромисс, выполняющий более статический анализ или оптимизацию, проходит во время компиляции, по существу, является (постоянно уменьшающимся) возвратом, который вы получаете от этой дополнительной силы против времени, которое требуется для запуска компилятора. Компилятор, такой как MLton (для стандартного ML), является компилятором, оптимизирующим целую программу, с множеством статических проверок. Он создает очень хороший код, но становится очень медленным в средних и крупных программах даже в быстрой системе.

Таким образом, подход Java, по-видимому, заключается в использовании JIT и адаптивной оптимизации в максимально возможной степени, причем исходный компиляционный проход просто создает приемлемый действительный двоичный файл. Абсолютным противоположным концом является использование такого подхода, как MLKit, который делает много статических выводов регионов и поведения памяти.