Должны ли мы избегать создания объектов на Java?

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

Кажется, это несколько портит цель объектно-ориентированного программирования. Если мы не создаем объекты, мы просто пишем один длинный класс C для оптимизации?

222 голоса | спросил Slamice 22 Mayam12 2012, 06:06:38

13 ответов


439

Ваш коллега понятия не имеет, о чем они говорят.

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

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

Все есть объект (кроме примитивов)

Все, кроме примитивов (int, long, double и т. д.), являются объектами в Java. Невозможно избежать создания объектов на Java.

Создание объекта на Java из-за его стратегий распределения памяти быстрее, чем C ++ в большинстве случаев и для всех практических целей по сравнению со всем остальным в JVM можно считать «бесплатным» .

В начале 1990-х годов в начале 2000-х годов реализации JVM имели некоторые накладные расходы на производительность при фактическом распределении объектов. Это было не так с 2005 года.

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

Он не пытается и максимизирует свободное пространство, которое является красной серой, так или иначе, оно максимизирует производительность среды выполнения. Если это означает, что куча JVM Heap почти 100% распределена все время, пусть будет так. Свободная куча памяти JVM не дает вам ничего, кроме как сидеть там.

Существует неправильное представление о том, что GC освободит память обратно в остальную часть системы полезным способом, это абсолютно неверно!

Куча JVM не растет и не уменьшается, поэтому на остальную часть системы положительно влияет свободная память в JVM Heap . -Xms выделяет ВСЕ то, что указано при запуске, и его эвристика - это никогда не выпускать какую-либо из этой памяти обратно в ОС для совместного использования с любыми другими процессами ОС до тех пор, пока этот экземпляр JVM не завершится полностью. -Xms = 1GB -Xmx = 1GB выделяет 1 ГБ ОЗУ независимо от того, сколько объектов фактически создано в любой момент времени. Существуют некоторые настройки, позволяющие освобождать проценты памяти кучи, но для < сильные> все практические цели JVM никогда не сможет выпустить достаточное количество этой памяти, чтобы это никогда не происходило , поэтому никакие другие процессы не могут вернуть эту память, поэтому остальная часть системы не использует JVM Heap также свободен. RFE для этого было «принято» 29-NOV-2006, но о нем ничего не было сделано. Это поведение не считается проблемой любого из авторитетов.

Существует неправильное представление о том, что создание множества небольших короткоживущих объектов заставляет JVM приостанавливаться в течение длительных периодов времени, теперь это также ложно.

Современные алгоритмы GC на самом деле оптимизированы для создания многих небольших объектов, которые недолговечны, что в основном 99% -ое эвристическое для объектов Java в каждой программе. Попытки Объединение объектов фактически сделают JVM хуже в большинстве случаев.

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

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

Объектно-ориентированные динамические языки избивают C even теперь дни на тестах, чувствительных к вычислению.

ответил Jarrod Roberson 22 Mayam12 2012, 06:33:14
80

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

В отличие от большинства ответов - да, распределение объектов У них есть связанная с этим стоимость. Это низкая стоимость, но вы должны избегать создания ненужных объектов. То же самое, что вам следует избегать ненужного в вашем коде. Графики больших объектов делают GC более медленным, подразумевая более длительное время выполнения, в котором вы, вероятно, будете иметь больше вызовов методов, вызывать больше промахов в кеш-памяти и повышать вероятность того, что ваш процесс будет заменен на диск в случаях с низкой оперативной памятью.

Прежде чем кто-нибудь из насчет того, чтобы это было краевым случаем, у меня есть профилированные приложения, которые перед оптимизацией создали 20 + МБ объектов для обработки ~ 50 строк данных. Это нормально при тестировании, пока вы не увеличите до сотни запросов в минуту, и вдруг вы создаете 2 ГБ данных в минуту. Если вы хотите сделать 20 запросов /сек, вы создаете 400 МБ объектов, а затем выбрасываете их. 20 reqs /sec является крошечным для достойного сервера.

ответил jasonk 22 Mayam12 2012, 06:41:15
58

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

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

ответил amara 22 Mayam12 2012, 06:20:21
35

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

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

  • Когда вы пишете приложение, чувствительное к задержкам, и хотите избежать пауз GC. Чем больше объектов вы производите, тем больше происходит GC и тем больше вероятность пауз. Это может быть актуальным для релевантных игр, некоторых медиа-приложений, роботизированного управления, высокочастотной торговли и т. Д. Решение состоит в том, чтобы предварительно выделить все объекты /массивы, которые вам нужны, и повторно использовать их. Существуют библиотеки, которые специализируются на предоставлении такого рода возможностей, например Javolution . Но, возможно, если вы действительно заботитесь о низкой задержке, вы должны использовать C /C ++ /ассемблер, а не Java или C #: -)
  • Избегание примитивов в штучной упаковке (Double, Integer и т. д.) может быть очень полезной микро-оптимизацией при определенных обстоятельствах. Поскольку unboxed primitives (double, int и т. Д.) Избегают накладных расходов для каждого объекта, они намного быстрее работают с интенсивным процессором, например, с числовой обработкой и т. Д. Обычно примитивные массивы отлично работают на Java, поэтому вы хотите использовать их для вашего хруста, а не любые другие виды объектов.
  • В ситуациях с ограниченной памятью вы хотите свести к минимуму количество (активных) объектов, созданных, поскольку каждый объект несет небольшие накладные расходы (обычно 8-16 байтов в зависимости от реализации JVM). В таких обстоятельствах вы должны предпочесть небольшое количество больших объектов или массивов для хранения ваших данных, а не большого количества небольших объектов.
ответил mikera 22 Maypm12 2012, 15:17:04
17

Есть ядро ​​истины в том, что говорит ваш коллега. Я с уважением предлагаю проблему с созданием объекта creation на самом деле является сборкой коллекции . В C ++ программист может точно контролировать, как освобождается память. Программа может накапливать crud как можно дольше или короче, чем нравится. Кроме того, программа на C ++ может отменить crud, используя другой поток, чем тот, который его создал. Таким образом, поток, который в настоящее время работает, никогда не должен останавливаться, чтобы очистить.

Напротив, виртуальная машина Java (JVM) периодически останавливает ваш код для восстановления неиспользуемой памяти. Большинство разработчиков Java никогда не замечают эту паузу, поскольку она обычно бывает нечастой и очень короткой. Чем больше вы накапливаете или чем более ограничено ваша JVM, тем чаще происходят эти паузы. Для визуализации этого процесса вы можете использовать такие инструменты, как VisualVM .

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

Когда это может произойти? В любое время, когда вы заботитесь о последовательных частотах ответа в миллисекундах, вы будете заботиться о GC. Автоматизированные торговые системы, написанные на Java, настраивают JVM для минимизации пауз. Фирмы, которые в противном случае пишут Java, превращаются в C ++ в ситуациях, когда системы должны быть очень отзывчивыми все время.

Для записи, я делаю не оправдывать обход объекта вообще! По умолчанию объектно-ориентированное программирование. Отрегулируйте этот подход только в том случае, если GC окажется на вашем пути, а затем только после попытки настроить JVM на паузу в течение меньшего времени. Хорошей книгой по настройке производительности Java является производительность Java от Charlie Hunt и Binu John.

ответил greg 22 Mayam12 2012, 07:34:45
11

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

Кроме того, эти ответы верны.

ответил Peter Kelly 22 Maypm12 2012, 12:30:39
8

GC настраивается для многих коротких объектов

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

В одном примере можно было бы построить строку в цикле, наивный способ был бы

String str = "";
в то время как (someCondition) {
    //...
    str + = appendingString;
}

, который создает новый объект String для каждой операции + = (плюс StringBuilder и новый базовый массив символов)

вы можете легко переписать это на:

StringBuilder strB = new StringBuilder ();
в то время как (someCondition) {
    //...
    strB.append (appendingString);
}
String str = strB.toString ();

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

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

ответил ratchet freak 22 Maypm12 2012, 12:43:00
6

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

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

ответил Oleksi 22 Mayam12 2012, 06:08:31
4

Джошуа Блох (один из разработчиков Java-платформы) написал в своей книге Эффективная Java в 2001 году:

  

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

ответил Anthony Ananich 3 +04002014-10-03T21:23:16+04:00312014bEurope/MoscowFri, 03 Oct 2014 21:23:16 +0400 2014, 21:23:16
3

Я думаю, что ваш коллега, должно быть, сказал с точки зрения создания ненужного объекта. Я имею в виду, что если вы часто создаете тот же объект, лучше делиться этим объектом. Даже в тех случаях, когда создание объекта является сложным и требует больше памяти, вы можете захотеть клонировать этот объект и не создавать этот сложный процесс создания объекта (но это зависит от вашего требования). Я думаю, что утверждение «Создание объекта дорого» должно быть принято в контексте.

Что касается требований к памяти JVM, дождитесь появления Java 8, вам даже не нужно указывать -Xmx, параметры метапространства будут заботиться о потребности в памяти JVM и будут автоматически расти.

ответил AKS 2 AM00000010000001831 2013, 01:48:18
1

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

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

ответил Alex 23 Mayam12 2012, 01:59:30
0

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

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

Вот отличная презентация на тему: https://www.cs.virginia.edu/kim/publicity/pldi09tutorials/memory-efficient-java-tutorial.pdf

ответил rkj 24 Mayam12 2012, 06:56:41
0

Я сделал быстрый microbenchmark относительно этого, и я предоставили полные источники в github. Мое заключение заключается в том, что создание объектов дорого или нет, но это не проблема, но постоянно создавая объекты с понятием, что GC позаботится о вас, сделает ваше приложение более запущенным процессом GC. GC - очень дорогостоящий процесс, и лучше всего избегать его, когда это возможно, и не пытаться подтолкнуть его к нажатию.

ответил Archimedes Trajano 25 Jam1000000amSun, 25 Jan 2015 04:24:00 +030015 2015, 04:24:00

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132