Когда собирать мусор - PullRequest
8 голосов
/ 18 июля 2009

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

System.gc();

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

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

... форсирует сборку мусора; чрезвычайно сомнительно, за исключением код тестирования

И это уточняет:

Код явно вызывает мусор коллекция. За исключением конкретного использования в бенчмаркинг, это очень сомнительно.

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

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

Ответы [ 8 ]

9 голосов
/ 18 июля 2009

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

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

btw: Вызов System.gc () рекомендует виртуальной машине выполнить «полный» или «большой» сбор, что означает, что все потоки будут вскоре остановлены. В противном случае он, вероятно, будет создавать только «маленькие» сборки мусора, которые не останавливают все потоки.

Запустите вашу программу с -verbose: gc, чтобы увидеть, сколько байт собрано.

Здесь также есть много технической информации о сборке мусора: http://java.sun.com/developer/technicalArticles/Programming/GCPortal/

9 голосов
/ 18 июля 2009

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

1 голос
/ 18 июля 2009

Если выделение памяти завершается неудачно, запускается цикл GC, и распределение повторяется.

1 голос
/ 18 июля 2009

Убедитесь, что крупные объекты можно собрать как можно раньше. То есть установите переменные в нуль и / или пусть они выпадают из области видимости. Это помогает!

1 голос
/ 18 июля 2009

У вас уже есть много хороших советов, которые я постараюсь не повторять.

Если у вас действительно возникают проблемы с GC, например, полная остановка вашего приложения на секунду, выполните следующие действия: 1. убедитесь, что нет никаких вызовов System.gc (); 2. проверить различные варианты настройки gc. Таких вокруг множество, и они гораздо полезнее, чем заставляют gc.

1 голос
/ 18 июля 2009

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

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

1 голос
/ 18 июля 2009

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

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

0 голосов
/ 18 июля 2009

Как правило, нет. Неуместно вызывать System.gc (). Однако у меня было несколько случаев, когда это имело смысл.

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

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

...