Ускорение Java

Это на самом деле два вопроса, но они настолько похожи, и, чтобы было проще, я решил, что я просто свожу их вместе:

  • Во-первых: учитывая устоявшийся Java-проект, какие есть приличные способы ускорить его помимо простой оптимизации в коде?

  • Во-вторых: при написании программы с нуля на Java, какие есть хорошие способы значительно повысить производительность?

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

Я спрашивал об Python и Perl ранее. Для Java мне интересно, какие хорошие советы / хитрости существуют для улучшения производительности и есть ли какие-либо особенно хорошие профилировщики Java.

15 ответов

Во-первых: при оптимизации кода я бы предположил, что вы сделали правильные алгоритмы и правильную реализацию алгоритмов. В этом случае вы должны использовать профилировщик и посмотреть, как часто ваш сборщик мусора (GC) собирает мусор и сколько времени он использует для этого. Затем вы начинаете работать над опциями GC - но будьте осторожны, вы можете столкнуться с проблемами, если не знаете, что делаете.
Я предполагаю, что вы используете Java 5/6. В этом случае я бы ознакомился с руководством по настройке java 5 по адресу http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html. Существует также очень хорошая новостная рассылка о производительности Java, которая называется http://www.javaperformancetuning.com/ на которую вы можете подписаться.

Кроме того, посмотрите, сколько блоков try / catch вы можете устранить. Посмотрите, сможете ли вы исключить ненужные выбросы исключений.

Используйте кэши, где вы можете, НО не переусердствуйте.

Читайте Эффективное Java, 1-е и / или 2-е издание

Профилировщики: я использую yourkit. Это очень хорошо для Java 1.5 и выше. Вы можете получить персональную лицензию. Другие профилировщики тоже хороши.

Так же, как у вас есть модульные и интеграционные тесты, не повредит иметь некоторые тесты производительности, которые вы выполняете как часть ваших сборок НЕПРЕРЫВНОЙ ИНТЕГРАЦИИ (CI). Таким образом, вы узнаете, когда вы регрессировали, особенно если вы используете хороший сервер сборки CI.

Убедитесь, что ваш уровень логов не случайно оставлен на DEBUG:)

"Мера, не угадай".
Вот хорошая статья об использовании NetBeans Profiler для ускорения работы библиотеки iText PDF. Я сам использовал NetBeans Profiler и обнаружил, что он очень прост и полезен для отслеживания некоторых проблем с производительностью, которые у меня были.

Для более старых приложений простой переход на Java 6 может повысить производительность. См. Этот технический документ для получения информации об улучшениях производительности в Java 6.

Используйте новейшие виртуальные машины - они постоянно улучшаются.

Профиль и тест. Никогда не оптимизируйте свой код, если вы не уверены, что вам это нужно.

Если это приложение с графическим интерфейсом, переключение с Swing на AWT или, возможно, инструментарий Eclipse, это должно быть довольно быстро. Это более важно на старых виртуальных машинах (я уже некоторое время работаю со встроенными системами, и мы находимся в версии 1.0.x, свинг даже не доступен)

Я знаю, что это не относится конкретно к Java, но не выделяет объекты - это включает в себя конкатенацию строк в цикле (вне цикла это довольно приемлемо. Это самая большая вещь, которую вы, вероятно, можете сделать.

Вы можете также держать объекты вокруг вместо того, чтобы освобождать / перераспределять их. Есть некоторые "ссылочные" классы, которые можно использовать для хранения объектов, которые вам не нужны, но, возможно, захотят использовать повторно - GC не удалит их, если ему не понадобится место.

Выделите больше места, если необходимо, с аргументом -MX.

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

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

Вам нужно не только взглянуть на процессорное время, но и на то, сколько памяти выделено и освобождено для определенного шага. Вы также хотите убедиться, что у вас нет утечек памяти или большого потребления памяти. Лучший инструмент для анализа потребления памяти, который я знаю, это Eclipse Memory Analyzer ( http://www.eclipse.org/mat).

Другие размеры - это проблемы с резьбой и проблемы с вводом-выводом. Простой способ анализа проблем с конфликтами можно найти в моем старом блоге по адресу https://www.sdn.sap.com/irj/sdn/weblogs?blog=/pub/wlg/4737

Использование StringBuilder вместо больших наборов конкатенации строк дает значительный относительный прирост производительности.

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

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

Некоторые сравнения

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

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

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

Хорошая особенность ООП заключается в том, что вы можете изменять реализации объекта без изменения интерфейса. Это позволяет начать кодирование с наивных реализаций и заменить их при необходимости.

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

Для профилирования попробуйте JAMON для мониторинга времени и профилировщик NetBeans для общего мониторинга производительности и памяти.

Java 1.6_07+ поставляется с собственным профилировщиком. Это называется Java VisualVM. Просто введите jvisualvm в командную строку, если у вас есть%JAVA_HOME%/bin в вашей переменной PATH.

Я видел, что иногда просто предоставление JVM большей кучи памяти помогает вялому приложению. Это контролируется с -xmx а также -xms Параметры JVM при запуске.

Есть одна вещь, которую вы должны сделать с самого начала проекта, которая будет огромной помощью: написать читаемый код.

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

Это может показаться неуместным, но на сайте разработчиков Android есть список советов по скорости. Он работает на телефоне с нестандартным байт-кодом dalvik, но многие из перечисленных здесь советов универсально применимы к Java в целом.

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

Другие вопросы по тегам