2011-01-07 6 views
4

У меня есть метод, который требует много времени для выполнения в первый раз. Но после нескольких обращений требуется примерно в 30 раз меньше времени. Таким образом, чтобы приложение быстрее реагировало на взаимодействие с пользователем, я «разминаю» этот метод (5 раз) с некоторыми примерами данных при инициализации приложения. Но это увеличивает время запуска приложения.
Я читал, что JVM может оптимизировать и скомпилировать мой Java-код на native, тем самым ускоряя работу. Я хотел знать - может быть, есть способ явно указать JVM, что я хочу, чтобы этот метод был скомпилирован при запуске приложения?Есть ли способ сказать JVM оптимизировать мой код перед обработкой?

+1

Вы действительно уверены, что он работает лучше, после того, как вызывается несколько раз именно из-за JVM оптимизаций. В зависимости от того, что делает ваш метод, это может быть и другое: например, кеширование диска или базы данных ... –

+0

@Rogach: вы не можете сначала оптимизировать свой метод? Что это за штука? – Gugussee

+0

Что именно делает этот метод? – Cratylus

ответ

6

JVM оптимизирует JiT (Just in Time) во время выполнения. Это означает, что он может анализировать, как выполняется ваш код, и сделать оптимизацию для повышения производительности во время выполнения. Это происходит при времени выполнения. Если вы видите, что метод ускоряется после нескольких исполнений, это, вероятно, связано с оптимизацией JiT (если ваш анализ не испорчен и, скажем, метод становится быстрее, потому что данные становятся проще). Если вы правильно проводите анализ, компиляция на носитель может навредить вам, потому что вы больше не сможете оптимизировать время выполнения.

Можем ли мы увидеть метод? Возможно, вы сможете сделать это быстрее, не беспокоясь о том, как работает JVM. Вы должны выделить точно, где наиболее затратные операции. Вы также должны убедиться, что это не какая-то проблема сбора мусора. то есть, возможно, этот метод прекрасен, но происходит GC, что означает время пережевывания, и когда это делается, ваш метод работает на приемлемых скоростях.

+0

относительно второго абзаца, есть ли хороший инструмент для профилирования выполнения Java-программы? Что-то вроде Shark, например (afaik, Shark! Работает только для Macintosh и для кода «C-like») – posdef

+0

@posdef, я просто искал SO для «лучшего бесплатного java-профайлера» и получил http://stackoverflow.com/questions/163722/which-java-profiler-is-better-jprofiler-or-yourkit – hvgotcodes

3

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

Возможно даже, что JIT-код отличается от разных запусков из-за разных входных данных. Или даже он может быть повторно опробован не раз, когда обстоятельства меняются.

Другими словами: без реальных данных JVM не будет делать хороший код оптимизации работы. (Т.е. он может делать только «статические» оптимизации)

Но в конце концов, если вы получаете так высоко улучшение (30x много!), То вполне вероятно, что это либо

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

EDIT:

После просмотра кода, в большой петле на Literas.prepareLiteras(), вы постоянно вызывающий path.contains(p) с разными точками, но тот же путь. SimplePath.contains() создает ограничительную форму каждый раз, когда он называется, поэтому вы снова и снова создаете ту же форму. Это яркий пример того, что нужно вытащить из внутреннего цикла.

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

2

Если вы используете Sun JVM, существуют разные пороговые значения для компиляции JIT, в зависимости от того, используете ли вы JVM клиента или сервера. Для клиента это 1500 вызовов метода, для сервера - 10000. Вы можете изменить это на очень низкое значение, используя параметр JVM -XX:CompileThreshold=100.

Такой низкий порог не принесет пользы для вашей глобальной производительности. Я предлагаю использовать его только для проверки того, влияет ли улучшение производительности на прогрев JIT.

Я никогда не видел улучшения с коэффициентом 30 путем разминки, что было связано с оптимизацией JIT. Все же. Это всегда было связано с некоторыми тайниками.

+0

Ничего себе. Это почти убивает приложение. Да, кажется, что улучшение не является результатом JIT. Этот параметр фактически делает вещи намного медленнее. – Rogach

+2

Ну, тогда попробуйте профайлер. Текущие JDK включают JVisualVM, который поставляется с базовым профилировщиком. –

2

Вы можете попробовать запустить это на 64-разрядной JVM, если у вас 64-разрядная операционная система.

Существует две версии JVM в реализации Oracle: клиентская VM и VM сервера. В 32-битной Windows клиентская виртуальная машина по умолчанию. В 64-битной Windows по умолчанию используется VM.

Разница между клиентской и серверной VM заключается в том, как они настраиваются: виртуальная машина сервера делает более агрессивные оптимизации (и делает их раньше), чем клиентская VM. На VM сервера оптимизированы параметры для длительных процессов. Клиентская виртуальная машина имеет настройки по умолчанию, которые оптимизированы для использования на настольных ПК: она делает меньше оптимизации на передней панели, но быстрее запускается.

Я испытал значительные различия в скорости в программах с интенсивным вычислением; они иногда работают в два раза быстрее на 64-битной JVM по сравнению с 32-разрядной JVM.

1

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

Смежные вопросы