Что следует искать при повышении производительности на Java?

Я работаю в команде поддержки большого проекта (около 7k + классов), и моя повседневная работа - это, в основном, исправление ошибок. Иногда, однако, у меня нет ошибок для работы. Когда это происходит, я большую часть времени проводил в поисках недостатков производительности в коде. Тот факт, что у меня есть более 7 тысяч классов, чтобы посмотреть, означает, что это не очевидно, чтобы найти эти пробелы.

Итак, я хотел бы знать , какие простые вещи следует искать при попытке повысить производительность системы?

Я не спрашиваю о конкретных методах кода, но об общих. Например:

  • Я уже искал все вхождения кода типа String a = new String("") и менял на StringBuilder a = new StringBuilder();
  • Я уже изменил весь доступ к базе данных, где это применимо, для использования PreparedStatement
  • Все записи Debug были удалены, а Finest были удалены, когда это возможно.

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

Ответы

Ответ 1

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

Оба из них включают в себя плагины Eclipse.

Ответ 2

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

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

Даже если бы у вас был список "вещей, которые нужно изменить без измерения производительности системы", действительно ли вы им доверяете, чтобы быть подходящими для ваших обстоятельств?

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

EDIT: Чтобы обратиться к нижестоящим (-ам) и настроениям "Я знаю, что с помощью PreparedStatement быстрее" - вместо того, чтобы просить серебряные пули, лучше задать вопрос, столкнувшись с этой проблемой, "как я могу продуктивно тратить свое свободное время на сделать вещи лучше?" ОП явно хочет улучшить ситуацию - это здорово... но без измерения "где это больно" он буквально стреляет в темноту. Является ли PreparedStatement быстрее? Конечно, но если реальная производительность gremlin находится в каком-то другом месте, зачем тратить время на "исправление" кода БД, когда вы можете сделать РЕАЛЬНОЕ влияние, если после фактических точек боли?

Еще одна вещь: в стабильной системе, такой как ОП описывает, изменение кода без хорошего количественного обоснования часто считается плохой практикой из-за введенных рисков. В таких стабильных системах вопрос о риске/вознаграждении - это ЛЮБОЕ изменение кода. Риск значителен: многие "простые, не могли сломать ничего", изменения поскользнулись в расписании выпуска/ввели серьезные проблемы. Награда? Неопределенно, поскольку вы на самом деле не знаете, повлияло ли ваше изменение на прирост производительности. Следовательно, мы профиль, чтобы убедиться, что мы улучшаем код, который имеет значение.

Ответ 3

Не изменяйте слепые вещи только потому, что они "выглядят" как возможно.

Подумайте об этом:

 logger.debug("Initializing object state " + object.initialize() );

Если вы просто и слепо удалите этот оператор, объект не будет инициализирован.

Конечно, такое утверждение ошибочно на первом месте, но, поверьте, они существуют!!!! И сделает вашу жизнь несчастной, если что-то подобное случится с вами.

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

Если у вас есть классы > 7k, очень вероятно, что вы просто фиксируете кучу кода, который вообще не используется.

ПРОФИЛЬ!!!!

Ответ 4

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

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

Ответ 5

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

Ответ 6

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

Я использую этот простой метод.

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

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

  • изменение базы данных
  • из-за инициализации структур данных
  • в процессе создания/уничтожения окон
  • в процессе изменения соединений в дереве-браузере
  • из-за переупорядочения элементов в списке
  • из-за операции вырезания/вставки
  • из-за того, что кто-то устанавливает свойство
  • из-за того, что кто-то установил "модифицированный" бит
  • бла, бла, бла...

иногда на 20-30 уровней.

Любой из этих слоев, которые появляются на нескольких образцах, если их можно было бы избежать, сэкономит большие проценты времени выполнения.

Ответ 7

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

Я побрил прямую 3 секунды этого вызова метода. Мне все равно, что он работает только один раз в пакетной работе каждые 12 лет.

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

Дерево вызовов

Invocation tree

Монитор памяти

Memory monitor

График вызовов

Call graph

Пожалуйста, просто Google" Профайлер Java.

Ответ 8

Я предлагаю использовать инструмент качества. В моем магазине используется сонар. Это поможет вам:

  • найти дубликат кода
  • найти сложные кодовые зоны
  • найти нарушение правила кода и возможные ошибки.
  • см. покрытие кода
  • см. недокументированный код

http://sonar.codehaus.org/

Ответ 9

Вы можете использовать инструменты статического анализа, такие как FindBugs. Компилятор javac уже пытается оптимизировать некоторые вещи. Компоны, такие как конкатенация строк, уже оптимизированы компилятором и преобразованы в строковый конструктор.

Если у вас есть сомнения, ничто не сравнится с профилировщиком, но остерегайтесь преждевременной оптимизации.

Ответ 10

В производительности сначала убедитесь, что у вас есть настоящая проблема, и если вы это сделаете, используйте профилировщик, например TPTP или JMeter. [edit: HPJMeter как раз был общим инструментом производительности Java, но теперь он специфичен для HP/UX). Интуиция - очень плохой путеводитель.

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

Ищите алгоритмические оптимизации, а не только низкоуровневые настройки кодирования Java. Они могут иметь огромные последствия.

Обязательно прочитайте настройку производительности Java для стратегий и идей.

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

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

Ответ 11

Правила оптимизации

  • Не делай этого.
  • Мера дважды.
  • Вы не должны здесь.
  • Не микро оптимизируйте. Ищите алгоритмическую сложность, такую ​​как используемые вами контейнеры.

Ответ 12

В общем:

  • Посмотрите на сложные разделы кода и посмотрите, можно ли их очистить.

  • Обратите особое внимание на циклы и посмотрите, можно ли улучшить их производительность для производительности

  • Рекурсивные вызовы, как правило, являются большими хитами в производительности. Убедитесь, что рекурсия обрабатывается должным образом и убедитесь, что любые биты рекурсии оправданы.

Ответ 13

Вместо того, чтобы сосредоточиться на "медленных" частях приложения, вы должны попытаться сосредоточиться на "плохих" частях приложения.

Существует автоматизированный инструмент, который поможет вам найти где ваш код ведет себя как CRAP

CRAP - действительно акроним для инструмента! Он делает некоторые полезные вещи, такие как проверка на цикломатическую сложность, но на самом деле дает вам 10-футовый взгляд на код

Также хороший профилировщик java может помочь вам найти узкие места, если они действительно есть.

Ответ 14

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

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

Ответ 15

Я бы изменил

Строка a = новая строка ( ");

к

Строка a =" ";

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

Прочитайте эффективные главы 2-го выпуска, посвященные Java.

Ответ 16

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

Ответ 17

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

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

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

Ответ 18

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

Вы можете посмотреть список на сайте FindBugs http://findbugs.sourceforge.net/bugDescriptions.html.

Ответ 19

Я согласен с остальными, что оптимизировать код SHOWN слишком медленно (с помощью профилировщика, с Java 6 u 10 и более поздним jvisualvm очень легко начать с).

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

  • Хороший javadoc для всех классов. Это помогает будущим сопровождающим быстрее понять код. В этом процессе разрешен простой рефакторинг.
  • Официальное место для страниц javadoc (поэтому разработчики могут связывать код с ними, что позволяет легко перемещаться, например Shift-F2 в Eclipse).
  • Тесты для библиотечных функций. По сути, это документация ALSO, поскольку она ясно демонстрирует, как использовать библиотеку и какие bordercases можно ожидать.
  • Определите способ запуска тестов и регенерации javadoc автоматически.
  • Определите способ запуска/тестирования/стресс вашего приложения автоматически. (Мышь нажимает на GUI, вызывается много запросов на веб-серверах и т.д.).

Любая из этих пуль будет улучшать базу кода без необходимости изменения кода без необходимости.

Ответ 20

Все лучшие улучшения производительности будут алгоритмическими улучшениями.

Ответ 21

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

Ответ 22

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

"Преждевременная оптимизация - это корень все зло". - Дональд Кнут

Ответ 23

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

Канонический пример представлен в C. Рассмотрим цикл

for (int ct=0; ct<strlen(str); ++ct) { ... }

Здесь strlen фактически сканирует массив char, который ищет символ терминатора NUL. Это операция O (n), которая делает весь цикл O (n ^ 2). Поэтому в C возьмите strlen снаружи с const int len = strlen(str);. Вы можете сделать то же самое на Java (я), но это имеет незначительное влияние на производительность. Код по вкусу.

Возвращаясь к вещам, которые действительно применимы к Java:

  • Напишите хороший код. Серьезно, неудачный код, как правило, скрывает проблемы с производительностью. Если вы сначала оптимизируете, то вы не сможете легко увидеть полезные оптимизации.
  • Знать и использовать библиотеки. Они, вероятно, быстрые и, скорее всего, будут разогреваться.
  • Позаботьтесь о выборе структур данных (на самом деле это не полезно, но нужно сказать).
  • Учитывайте объем памяти, который использует ваша структура данных. Это часто скрывается с микрообъектами и влияет на производительность системы не локально.
  • Используйте ArrayList вместо LinkedList. Вы можете найти подробности здесь и в других местах, но LinkedList имеет тенденцию быть медленным, даже если вы считаете, что это будет быстро.
  • Рассмотрим, какая часть производительности приложения имеет решающее значение. Например, ответ на перемещение мыши, вероятно, всегда будет прекрасным, но открытие диалога может иметь заметную задержку (менее важно на общих серверах).
  • Помните, что процессор быстрее, чем кеш, быстрее, чем основная память, быстрее, чем локальная сеть/диск, быстрее, чем в Интернете, быстрее, чем веб-службы.
  • Рассмотрим печальный случай, а также счастливый случай.

Ответ 24

Если ваш код использует несколько критических структур данных и особенно карты/наборы/все, что связано с большим количеством поисковых запросов, вы можете убедиться, что используете их оптимально.

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

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

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

Ответ 25

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

Ответ 26

Вы можете посмотреть такие инструменты, как FindBugs, но они не исправят ваш код. Я предлагаю вам попробовать IntelliJ Community Edition, который является бесплатным. Это найдет возможную проблему с производительностью, а также даст вам быстрые исправления.

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