Подтвердить что ты не робот

Рекомендации по производительности Java

У меня есть программа, которую я портировал с C на Java. Оба приложения используют quicksort для упорядочения некоторых секционированных данных (геномных координат).

Версия Java работает быстро, но я хотел бы приблизиться к версии C. Я использую Sun JDK v6u14.

Очевидно, что я не могу получить паритет с приложением C, но я хотел бы узнать, что я могу сделать, чтобы вывести столько производительности, насколько это возможно (в пределах среды).

Какие вещи я могу сделать для проверки производительности разных частей приложения, использования памяти и т.д.? Что бы я сделал, в частности?

Кроме того, какие трюки можно реализовать (в общем) для изменения свойств и организации моих классов и переменных, сокращения использования памяти и повышения скорости?

EDIT. Я использую Eclipse и, очевидно, предпочитаю бесплатные опции для любых сторонних инструментов. Спасибо!

4b9b3361

Ответ 1

не пытайтесь перехитрить jvm.

в частности:

  • не пытайтесь избежать создания объекта ради производительности

  • используйте неизменяемые объекты, где применимо.

  • используйте область ваших объектов правильно, чтобы GC мог работа.

  • используйте примитивы, где вы имеете в виду примитивы (например, non-nullable int по сравнению с нулевым целым числом)

  • использовать встроенные алгоритмы и структуры данных

  • при передаче concurrency используйте пакет java.util.concurrent.

  • правильность работы. сначала сделайте это правильно, затем измерьте, затем измерьте с помощью профилировщика, затем оптимизируйте.

Ответ 2

Очевидно, профиль профиля профиля. Для Eclipse есть TPTP. Вот статья о плагине TPTP для Eclipse. Netbeans имеет свой собственный profiler. jvisualvm является приятным как автономный инструмент. (Весь сервер dev.java.net, похоже, сейчас не работает, но это очень активный проект.)

Первое, что нужно сделать, это использовать процедуру сортировки библиотеки, Collections.sort; это потребует, чтобы ваши объекты данных были Comparable. Это может быть достаточно быстрым и, безусловно, будет хорошим исходным уровнем.

Общие советы:

  • Избегайте блокировок, которые вам не нужны (ваша JVM, возможно, уже оптимизировала их)
  • Используйте StringBuilder (не StringBuffer из-за этой блокировки, о которой я только что упомянул) вместо конкатенирования объектов String
  • Сделайте что-нибудь, что вы можете final; если возможно, сделать ваши классы совершенно неизменными.
  • Если вы не изменяете значение переменной в цикле, попробуйте его вытащить и посмотрите, не имеет ли это значение (возможно, JVM уже сделала это для вас)
  • Попытайтесь работать с ArrayList (или даже массивом), чтобы доступная вам память была смежной, а не потенциально фрагментированной это может быть с LinkedList
  • Quicksort может быть распараллелен; подумайте об этом (см. рассогласование быстрой сортировки)
  • Уменьшите видимость и время жизни ваших данных как можно больше (но не делайте этого, если не профилируйте, это большой выигрыш)

Ответ 3

Использовать профайлер:

  • visualvm (бесплатный, ограниченный)
  • jprofiler (коммерческий)
  • yourkit java profiler (коммерческий)
  • hprof (бесплатный, ограниченный, только консоль)

Используйте последнюю версию JVM у своего провайдера. Кстати, обновление Sun Java 6 update 14 приносит улучшения производительности.

Измерьте пропускную способность GC и выберите лучший сборщик мусора для вашей рабочей нагрузки.

Ответ 4

Не оптимизируйте преждевременно.

Измерьте производительность, затем оптимизируйте.

Используйте конечные переменные, когда это возможно. Это не только позволит JVM   оптимизировать больше, но   код легче читать и поддерживать.

Если вы делаете свои объекты неизменными, вам не нужно клонировать их.

Оптимизируйте сначала, изменив алгоритм, затем изменив реализацию.

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

Ответ 5

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

-XX:+DoEscapeAnalysis 

Ответ 6

jvisualvm теперь отправляется с JDK 6 - причина, по которой ссылка, приведенная выше, не работает. Просто введите "jvisualvm <pid> ", где <pid> это идентификатор процесса, который вы хотите отслеживать. Вы увидите, как используется куча, но вы не увидите, что его заполняет.

Если это длительный процесс, вы можете включить параметр -server при запуске. Есть много вариантов настройки, доступных вам; что только один.

Ответ 7

Прежде всего, перед тем, как приступить к любой работе по оптимизации, убедитесь, что вы выполнили соответствующий профилирование или сравнительный анализ. Результаты часто будут просвещать вас и почти всегда сэкономить много усилий в оптимизации чего-то, что не имеет значения.

Предполагая, что вам это нужно, вы можете получить производительность, сравнимую с C на Java, но это требует определенных усилий. Вам нужно знать, где JVM делает "дополнительную работу" и избегать этого.

В частности:

  • Избегайте создания ненужного объекта. В то время как куча JVM и GC чрезвычайно быстрая и эффективная (возможно, лучшая в мире и почти наверняка лучше, чем все, что вы могли бы наброситься на C), она по-прежнему является распределением кучи, и это будет избито, избегая кучи в первом место (распределение стека или регистра)
  • Избегайте примитивов в коробке. Вы хотите использовать double, а не double.
  • Использовать примитивные массивы для любых больших фрагментов данных. Java-примитивные массивы в основном такие же быстрые, как массивы C/С++ (у них есть дополнительная проверка границ, но это обычно несущественно)
  • Избегать чего-либо синхронизированного - потоки Java довольно приличные, но вам все равно накладные расходы. Дайте каждому потоку свои данные для работы.
  • Exploit concurrency - поддержка Java concurrency очень хорошая. Вы могли бы использовать все свои ядра! Это большая тема, но есть много хороших книг/учебных пособий.
  • Использовать специализированные классы коллекций для определенных типов данных, если у вас есть некоторые очень специфические требования, например. поддерживая некоторые специализированные алгоритмы сортировки/поиска. Возможно, вам придется сворачивать свои собственные, но есть также хорошие библиотеки с высокопроизводительными наборами классов, которые могут соответствовать вашим потребностям - см., Например, Javoltion
  • Избегайте иерархии больших классов - это запах дизайна в коде производительности. Каждый слой абстракции стоит вам над головой. Очень быстрый Java-код часто будет выглядеть скорее как C....
  • Использовать статические методы - JIT может оптимизировать их очень хорошо. Как правило, они встраиваются в них.
  • Используйте конечные конкретные классы - снова JIT может оптимизировать их очень хорошо, избегая вызовов виртуальных функций.
  • Создайте собственный байт-код - если все остальное не удается, это может быть жизнеспособным вариантом, если вы хотите получить абсолютную максимальную производительность из JVM. Особенно полезно, если вам нужно скомпилировать собственный DSL. Используйте что-то вроде ASM.

Ответ 8

Если ваш алгоритм тяжелый CPU, вы можете рассмотреть возможность использования параллелизации. Вы можете сортировать по нескольким потокам и объединять результаты позже.

Это, однако, не решение, которое нужно воспринимать легкомысленно, так как сложность записи параллельного кода затруднительна.

Ответ 9

Не можете ли вы использовать функции сортировки, которые включены в библиотеку Java?

Вы можете по крайней мере посмотреть на разницу в скорости между двумя функциями сортировки.

Ответ 10

Методологически вам необходимо профилировать приложение, а затем получить представление о том, какие компоненты вашей программы имеют время и интенсивность памяти: затем более внимательно посмотрите на эти компоненты, чтобы улучшить их производительность (см. Закон Amdahl).

Из чистого технологического POV вы можете использовать некоторые компиляторы java-to-nativecode, такие как Excelsior jet, но я должен отметить, что последние JVM очень быстрые, поэтому виртуальная машина не должна влиять значительным образом.

Ответ 11

Выполняется ли ваш код сортировки только один раз, например. в утилите командной строки, которая просто сортирует или несколько раз, например. webapp, который сортируется в ответ на некоторый ввод пользователя?

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

Это большое преимущество по сравнению с C/С++.

VM во время выполнения оптимизирует код, который используется часто, и он делает это достаточно хорошо. Из-за этого производительность может выйти за пределы C/С++. В самом деле.;)

Однако ваш пользовательский Компаратор может быть местом для оптимизации.

Попробуйте сначала проверить недорогие вещи (например, сравнение int) перед более дорогим материалом (например, сравнение строк). Я не уверен, что эти советы применяются, потому что я не знаю вашего компаратора.

Используйте либо Collections.sort(список, компаратор), либо Arrays.sort(массив, компаратор). Вариант массива будет немного быстрее, см. Соответствующую документацию.

Как сказал ранее Андреас: не пытайтесь перехитрить VM.

Ответ 12

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

Или продайте некоторое пространство на диске /RAM для скорости, или если вы можете отказаться от некоторого времени во время загрузки вашей программы, вы можете предварительно скопировать таблицы поиска вместо выполнения вычислений - таким образом, обработка выполняется быстро. I.e., сделать некоторые компромиссы других ресурсов.

Ответ 13

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

Ответ 14

Профиль и настройте свою Java-программу и хост-машину. Большая часть кода соответствует правилу 80/20. Это 20% кода 80% времени, поэтому найдите 20% и сделайте это как можно быстрее. Например, статья Tuning Java Servers (http://www.infoq.com/articles/Tuning-Java-Servers) содержит описание детализации из командной строки, а затем изолирует проблему с помощью таких инструментов, как Java Flight recorder, Eclipse Memory Analyzer и JProfiler.