Сборщик мусора занимает слишком много процессорного времени - PullRequest
5 голосов
/ 09 марта 2012

Я разработал веб-приложение, которое обрабатывает огромное количество данных и занимает много времени?

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

Интересно, есть ли способ улучшить это? Я не хочу тратить столько времени на свои процессоры только в GC. Ниже приведены некоторые детали, которые могут быть полезны:

  1. Я использую Java 1.6.0.23
  2. Мое приложение занимает максимум 20 ГБ памяти.
  3. Полный GC происходит через каждые 14 минут.
  4. Память до ГХ составляет 20 ГБ, а после ГХ - 7,8 ГБ
  5. Память, используемая в ЦП (т. Е. Показанная в диспетчере задач), составляет 41 ГБ.
  6. После завершения процесса (JVM все еще работает) Используемая память 5 ГБ и свободная память 15 ГБ.

Ответы [ 5 ]

5 голосов
/ 09 марта 2012

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

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

Чтобы помочь JVM использовать этот алгоритм, избегайте циклических ссылок (объект A ссылается на B, затем B ссылается на C, C ссылается на D .... и снова Z ссылается на A). Потому что даже когда весь граф объекта недоступен, ни один из счетчиков ссылок объекта не достигает нуля.

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

4 голосов
/ 09 марта 2012

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

4 голосов
/ 09 марта 2012

Если вы используете 64-битную архитектуру, добавьте:

-XX:+UseCompressedOops 64-битные адреса преобразуются в 32-битные

Используйте G1GC вместо CMS:

-XX:+UseG1GC - используются пошаговые шаги

Установите одинаковый начальный и максимальный размер: -Xms5g -Xmx5g

Параметры настройки (только пример):

-XX:MaxGCPauseMillis=100 -XX:GCPauseIntervalMillis=1000

См. Параметры виртуальной машины Java HotSpot Параметры производительности

3 голосов
/ 09 марта 2012

Чем меньше вещей вы new, тем меньше нужно собирать вещей.

Предположим, у вас есть класс А. Вы можете включить в него ссылку на другой экземпляр класса А. Таким образом, вы можете сделать«бесплатный список» экземпляров A. Если вам нужен A, просто вытолкните один из списка бесплатных.Если свободный список пуст, тогда new один.

Когда он вам больше не нужен, добавьте его в свободный список.

Это может сэкономить много времени.

3 голосов
/ 09 марта 2012

Количество времени, проведенного в ГХ, зависит от двух факторов:

  • Сколько объектов живое (= может быть достигнуто от любого)
  • Сколько реализовано мертвых объектов finalize()

Объекты, которые не могут быть достигнуты и которые не используют finalize(), ничего не стоят для очистки в Java, поэтому Java обычно находится на одном уровне с другими языками, такими как C ++ (и часто намного лучше, потому что C ++ тратит много время для удаления объектов).

Итак, что вам нужно сделать в вашем приложении, это сократить количество объектов, которые выжили, и / или сократить ссылки на объекты (которые вам больше не нужны) ранее в коде. Пример:

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

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

...