Что ж, тут несколько вопросов в одном!
1 - Как управляются недолговечные объекты?
Как указывалось ранее, JVM может отлично справиться с огромным количеством короткоживущих объектов, поскольку следует гипотезе слабого поколения .
Обратите внимание, что мы говорим об объектах, которые достигли основной памяти (кучи). Это не всегда так. Многие создаваемые вами объекты даже не покидают регистр ЦП. Например, рассмотрим этот цикл for
for(int i=0, i<max, i++) {
// stuff that implies i
}
Давайте не будем думать о развертывании цикла (оптимизации, которую JVM серьезно выполняет в вашем коде). Если max
равно Integer.MAX_VALUE
, выполнение цикла может занять некоторое время. Однако i
переменная никогда не выйдет из блока цикла. Поэтому JVM поместит эту переменную в регистр ЦП, регулярно будет увеличивать ее, но никогда не будет отправлять ее обратно в основную память.
Итак, создание миллионов объектов не представляет большого труда, если они используются только локально. Они будут мертвы до того, как будут сохранены в Эдеме, поэтому ГК их даже не заметит.
2 - Полезно ли уменьшить накладные расходы на сборщик мусора?
Как обычно, это зависит от обстоятельств.
Во-первых, вы должны включить ведение журнала GC, чтобы иметь четкое представление о том, что происходит. Вы можете включить его с помощью -Xloggc:gc.log -XX:+PrintGCDetails
.
Если ваше приложение проводит много времени в цикле сборщика мусора, то да, настройте сборщик мусора, в противном случае оно того не стоит.
Например, если у вас есть молодой сборщик мусора каждые 100 мс, который занимает 10 мс, вы проводите 10% своего времени в сборщике мусора, и у вас есть 10 сборов в секунду (что очень много). В таком случае я бы не стал тратить время на настройку сборщика мусора, поскольку эти 10 сборщиков мусора в секунду все равно будут там.
3 - Некоторый опыт
У меня была аналогичная проблема с приложением, которое создавало огромное количество заданного класса. В журналах GC я заметил, что скорость создания приложения составляла около 3 ГБ / с, что слишком много (да ладно ... 3 гигабайта данных каждую секунду ?!).
Проблема: слишком много частых сборщиков мусора из-за создания слишком большого количества объектов.
В моем случае я подключил профилировщик памяти и заметил, что класс представляет собой огромный процент всех моих объектов. Я отследил экземпляры, чтобы выяснить, что этот класс в основном представляет собой пару логических значений, заключенных в объект. В этом случае было доступно два решения:
Измените алгоритм, чтобы я не возвращал пару логических значений, а вместо этого у меня было два метода, которые возвращают каждое логическое значение отдельно.
Кешируйте объекты, зная, что было всего 4 разных экземпляра
Я выбрал второй, так как он меньше всего повлиял на приложение и его было легко внедрить. Мне потребовалось несколько минут, чтобы создать фабрику с небезопасным кешем (потокобезопасность мне не нужна, поскольку в конечном итоге у меня будет только 4 разных экземпляра).
Скорость выделения снизилась до 1 ГБ / с, как и частота молодых GC (деленная на 3).
Надеюсь, это поможет !