Есть ли проблемы с производительностью из-за использования большого количества объектов в Java?

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

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


person bjedrzejewski    schedule 31.07.2013    source источник
comment
Честно говоря, объекты имеют большее влияние на производительность, чем примитивы (в меньшей степени, если они недолговечны), но прежде чем принимать какое-либо решение, профилируйте, убедитесь, что это серьезное узкое место, потому что способ примитивов вероятно, будет намного менее дружелюбным к программисту   -  person Richard Tingle    schedule 31.07.2013
comment
Честно говоря, меня больше беспокоит работа с большим количеством объектов - время создания не имеет большого значения. Мне интересно, как это можно профилировать, не переписывая большую часть кода.   -  person bjedrzejewski    schedule 31.07.2013
comment
Я не понимаю, профилировщик сгруппирует их все вместе, если они все созданы в одном месте (например, в цикле)   -  person Richard Tingle    schedule 31.07.2013
comment
Профиль использует VisualVM или JProfiler   -  person Narendra Pathai    schedule 01.08.2013


Ответы (4)


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

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

Возможно, вы захотите подумать, какие структуры лучше подходят для кешей ЦП, поскольку это может повысить производительность в 2-5 раз. например Ваш кеш L3 может быть 8 МБ и более чем в 5 раз быстрее, чем основная память. Чем больше вы сможете сжать свой рабочий набор, чтобы вписаться в него, тем лучше.

Кстати, ваш кеш L1 составляет 32 КБ и снова примерно в 10 раз быстрее.

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

person Peter Lawrey    schedule 31.07.2013
comment
Предполагая, что скорость ввода и вывода вашего кеша, конечно, высока. Хорошие предложения, +1 - person William Morrison; 31.07.2013

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

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

person assylias    schedule 31.07.2013

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

Но что касается вашего вопроса...

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

Опять же, беспокойтесь об этом только в том случае, если вам действительно нужно улучшить скорость.

person William Morrison    schedule 31.07.2013
comment
некоторые склонны маскировать отсутствие экспертных знаний в предметной области как желание не проводить преждевременную оптимизацию, желание заранее принимать разумные проектные решения — это хорошо, а не преждевременная оптимизация. - person bobah; 31.07.2013
comment
Именно поэтому я предлагаю смоделировать систему во втором предложении @bobah. Я также утверждаю, что время, потраченное на это, того стоит. Что ты пытаешься сказать? - person William Morrison; 31.07.2013
comment
ваш ответ подразумевает, что автор пытается что-то преждевременно оптимизировать - person bobah; 31.07.2013
comment
Да, это так, и да, он мог бы. Но опять же, поскольку я предложил моделирование для определения необходимой конструкции системы, прежде чем тратить время на оптимизацию, я считаю ваш комментарий нелогичным. - person William Morrison; 31.07.2013

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

В конце концов, ваше узкое место может быть одним из следующих:

  • CPU, потому что, если вычислительная сложность алгоритма => попробуйте найти лучший алгоритм (или запустите несколько процессоров параллельно, если вы немного отстаете от цели, если вы намного ниже, то параллельная обработка не поможет)
  • ЦП из-за чрезмерного GC => память профиля, используйте коллекции low/zero-GC (trove4j и т. д.) или даже массивы примитивных типов, или даже прямые буферы памяти из NIO, поэкспериментируйте
  • Память — оптимизируйте близость данных (используйте фрагментированные массивы, соответствующие размерам кеша и т. д.).
  • Конкуренция за параллельные объекты => вернуться к однопоточному дизайну, попробовать примитивы синхронизации без блокировки и т. д.
person bobah    schedule 31.07.2013