Объединение объектов - PullRequest
       12

Объединение объектов

14 голосов
/ 25 марта 2009

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

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

Ответы [ 7 ]

21 голосов
/ 25 марта 2009

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

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

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

Время GC не уменьшается. На самом деле это может быть хуже. С движущимися ГХ поколений (Java был или был до 1,5) стоимость прогона ГХ определяется количеством живых объектов, а не освобожденной памятью. Живые объекты будут перемещены в другое пространство в памяти (это то, что делает выделение памяти таким быстрым: свободная память непрерывна внутри каждого блока GC) пару раз, прежде чем быть помеченным как old и перемещено в старшее поколение пространство памяти.

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

18 голосов
/ 25 марта 2009

Если бы объект не был дорогим для создания, я бы не стал беспокоиться.

Преимущества:

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

Downsides:

  • более сложный код
  • Общий ресурс = блокировка; потенциальное узкое место
  • Нарушает ожидания GC относительно времени жизни объектов (большинство объектов будет недолговечным)

У вас есть реальная проблема, которую вы пытаетесь решить, или это спекулятивный вопрос? Я бы не стал делать что-то подобное, если у вас нет тестов / профилей, показывающих, что есть проблема.

9 голосов
/ 25 марта 2009

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

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

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

5 голосов
/ 25 марта 2009

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

Пример из реальной жизни: мне нужно было периодически извлекать n элементов с наивысшим рейтингом (целые числа) из процесса, генерирующего большое количество пар целое число / ранг. Я использовал объект «pair» (целое число и значение с плавающей точкой) в очереди с ограниченным приоритетом. Повторное использование пар по сравнению с очисткой очереди, выбрасыванием пар и повторным их созданием дало повышение производительности на 20% ... в основном за счет сборщика мусора, потому что пары не нужно было перераспределять в течение всего срока службы JVM.

5 голосов
/ 25 марта 2009

Не.

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

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

Иди вперед и запусти профиль по созданию 1 000 000 объектов. Это незначительно.

Старая статья здесь.

3 голосов
/ 27 марта 2009

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

2 голосов
/ 25 марта 2009

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

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

...