Стоит ли минимизировать создание множества мелких предметов?

10

При написании чего-то, что часто создает множество (1000 с) небольших объектов, следует ли пытаться минимизировать это для производительности? Особенно, если вы не знаете, на какой системе он будет работать, от низкоуровневых настольных компьютеров до мобильных устройств. Что касается мобильных устройств, я слышал, что создание большого количества объектов сильно снижает производительность, хотя я не знаю, насколько это правда.

У меня есть пример, который хорошо показывает эту идею. Скажем, в графической программе есть метод, который в идеале вызывается для всего рисования drawPixel(Point). Может быть создано 1000 точек, и их можно часто повторять, как в игре, где их можно вызывать более 60 раз в секунду. В качестве альтернативы drawPixel(int x, int y)может использоваться для минимизации создания множества объектов Point.

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

Stripies
источник
Мне трудно найти ссылки, чтобы поддержать это, но в целом в Java 8 просто не беспокойтесь об этом. Не делайте явно глупых вещей, но если вы не намеренно расточительны, система должна работать просто отлично. У Sun / Oracle было около 20 лет, чтобы настроить GC и управление памятью, и они действительно добились в этом хороших результатов.
@ Снеговик Я слышал, что более новые версии Java лучше справляются с управлением памятью, но проблема, которую я вижу, состоит в том, что нет никакой гарантии, что пользователь не использует более старую версию. Это часть того, что создало мою заботу.
Полосатые
1
Сначала сделайте некоторое измерение производительности. Если у вас есть проблемы, подумайте, как оптимизировать. Но, пожалуйста, не жертвуйте обслуживаемостью кода слишком рано, потому что вы думаете, что у вас могут быть проблемы с производительностью.
Пятнистый
2
@Stripies Производительность недолговечных объектов Java уже дана в ответе. Следует ли избегать создания объектов в Java? , Однако если вам когда-нибудь придется обрабатывать сотни миллионов таких объектов в секунду, то только в этот момент пересмотрите эту проблему.
Руонг
1
Если вы беспокоитесь о старых версиях Java, проверьте это при установке. JVM, достаточно старая, чтобы вызвать проблемы с управлением памятью, также имеет множество хорошо известных проблем безопасности, поэтому побуждение пользователей к обновлению делает им одолжение. System.getProperty("java.version")(или "java.vm.version") является отправной точкой.
Джерри Гроб

Ответы:

17

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

  1. Использование объектов является своего рода точкой использования Java. Превентивный отказ от них является признаком того, что решение использовать Java, возможно, не было правильным с самого начала.
  2. Проблемы с производительностью общеизвестно сложно предсказать. Никогда не предполагайте, что что-то является узким местом. Всегда измеряй. Эффективное проектирование - это почти всегда вопрос небольших изменений в нужном месте. Вы не можете предсказать правильное место, не измеряя больше, чем вы можете предсказать эффект лекарства без эксперимента.
  3. Стоимость создания объекта сильно завышена. В современной JVM это сводится в основном к приращению указателя (а для сборщиков мусора поколений затраты на его управление также тривиальны). В Интернете много текстов, которые советуют вам избегать объектов, использовать пул объектов и т. Д. Этот совет иногда был правильным в 1990-х годах; сегодня это в основном устарело. Очень маловероятно, что вы получите достаточную производительность, чтобы оправдать добавленные затраты на разработку и сложность, связанные с отказом от Объектов или управлением ими самостоятельно.

Тем не менее, есть места, где начинать что-либо в объект не имеет смысла с самого начала. Передача двух координат в процедуру рисования может быть таким случаем: пара координат не имеет независимого существования, она не имеет идентичности, она используется только один раз, а затем сразу отбрасывается и т. Д.

Если это так, то, конечно, продолжайте и передайте две intсекунды, а не оборачивайте их в объект. Суть ООП не в том, что все должно быть объектом. Дело в том, что объекты облегчают разработку в тех местах, где они являются естественным решением проблемы представления данных. Не избегайте объектов там, где они имеют смысл - не вводите их там, где их нет.

Килиан Фот
источник
2

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

Существует очень мало места для объектов в Java по сравнению с примитивами. Чем мельче ваши объекты, тем больше будет процент накладных расходов. Однако я давно узнал, что вещи, которые удваивают n, ничто по сравнению с вещами, которые умножают n на n.

Так что, хотя да, вы можете найти какую-то систему, которая имела бы половину размера или даже четвертую, спросите себя, почему вы действительно заботитесь. Сложные решения этой проблемы не будут приняты хорошо. Тем более, что погружение в такой кодекс будет сбивать с толку. Смущенные программисты пишут плохой код. Они пишут n раз n кода, который должен быть n log n code. И они занимают больше времени, чтобы сделать это.

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

candied_orange
источник
2

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

Я делаю это только если мне нужно делать предметы. Для графики, как правило, нет. ИМХО, графика должна быть нарисована , а не построена . Конечно, вы можете сказать, что картинка состоит из точек, линий, которые их соединяют, полигонов, текста и так далее. Это не значит, что у вас нет альтернативы созданию объектов из них до того, как вы их нарисуете . Я просто рисую их.

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

ООП - хорошая идея по определенным причинам. Эти причины не применимы во всех ситуациях.

Майк Данлавей
источник
Я согласен, но я также согласен со всеми остальными, что тестирование - это единственный способ узнать наверняка. Убедитесь, что у вас есть спецификации, делающие это простым / очевидным способом, прежде чем оптимизировать его ... но я согласен, что новое все еще может быть проблемой.
Билл К
2

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

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

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

Билл Фергюсон
источник
1

Все просто: если вам нужно 1000 маленьких объектов, вы создаете 1000 маленьких объектов и не беспокоитесь об этом. Если вам нужно 100 маленьких объектов, то создавать 1000 маленьких объектов глупо - создавайте те, которые вам нужны, а не больше.

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

gnasher729
источник