problem g1gc как исправить
Garbage First Garbage Collector Tuning
by Monica Beckwith
Published August 2013
Learn about how to adapt and tune the G1 GC for evaluation, analysis and performance.
The Garbage First Garbage Collector (G1 GC) is the low-pause, server-style generational garbage collector for Java HotSpot VM. The G1 GC uses concurrent and parallel phases to achieve its target pause time and to maintain good throughput. When G1 GC determines that a garbage collection is necessary, it collects the regions with the least live data first (garbage first).
A garbage collector (GC) is a memory management tool. The G1 GC achieves automatic memory management through the following operations:
Here, we look at how to adapt and tune the G1 GC for evaluation, analysis and performance—we assume a basic understanding of Java garbage collection.
The G1 GC is a regionalized and generational garbage collector, which means that the Java object heap (heap) is divided into a number of equally sized regions. Upon startup, the Java Virtual Machine (JVM) sets the region size. The region sizes can vary from 1 MB to 32 MB depending on the heap size. The goal is to have no more than 2048 regions. The eden, survivor, and old generations are logical sets of these regions and are not contiguous.
The G1 GC has a pause time-target that it tries to meet (soft real time). During young collections, the G1 GC adjusts its young generation (eden and survivor sizes) to meet the soft real-time target. During mixed collections, the G1 GC adjusts the number of old regions that are collected based on a target number of mixed garbage collections, the percentage of live objects in each region of the heap, and the overall acceptable heap waste percentage.
The G1 GC reduces heap fragmentation by incremental parallel copying of live objects from one or more sets of regions (called Collection Set (CSet)) into different new region(s) to achieve compaction. The goal is to reclaim as much heap space as possible, starting with those regions that contain the most reclaimable space, while attempting to not exceed the pause time goal (garbage first).
The G1 GC uses independent Remembered Sets (RSets) to track references into regions. Independent RSets enable parallel and independent collection of regions because only a region’s RSet must be scanned for references into that region, instead of the whole heap. The G1 GC uses a post-write barrier to record changes to the heap and update the RSets.
Garbage Collection Phases
Apart from evacuation pauses (described below) that compose the stop-the-world (STW) young and mixed garbage collections, the G1 GC also has parallel, concurrent, and multiphase marking cycles. G1 GC uses the Snapshot-At-The-Beginning (SATB) algorithm, which takes a snapshot of the set of live objects in the heap at the start of a marking cycle. The set of live objects is composed of the live objects in the snapshot, and the objects allocated since the start of the marking cycle. The G1 GC marking algorithm uses a pre-write barrier to record and mark objects that are part of the logical snapshot.
Young Garbage Collections
The G1 GC satisfies most allocation requests from regions added to the eden set of regions. During a young garbage collection, the G1 GC collects both the eden regions and the survivor regions from the previous garbage collection. The live objects from the eden and survivor regions are copied, or evacuated, to a new set of regions. The destination region for a particular object depends upon the object’s age; an object that has aged sufficiently evacuates to an old generation region (that is, promoted); otherwise, the object evacuates to a survivor region and will be included in the CSet of the next young or mixed garbage collection.
Mixed Garbage Collections
Upon successful completion of a concurrent marking cycle, the G1 GC switches from performing young garbage collections to performing mixed garbage collections. In a mixed garbage collection, the G1 GC optionally adds some old regions to the set of eden and survivor regions that will be collected. The exact number of old regions added is controlled by a number of flags that will be discussed later (see «Taming Mixed GCs»). After the G1 GC collects a sufficient number of old regions (over multiple mixed garbage collections), G1 reverts to performing young garbage collections until the next marking cycle completes.
Phases of the Marking Cycle
The marking cycle has the following phases:
Important Defaults
The G1 GC is an adaptive garbage collector with defaults that enable it to work efficiently without modification. Here is a list of important options and their default values. This list applies to the latest Java HotSpot VM, build 24. You can adapt and tune the G1 GC to your application performance needs by entering the following options with changed settings on the JVM command line.
Sets the size of a G1 region. The value will be a power of two and can range from 1MB to 32MB. The goal is to have around 2048 regions based on the minimum Java heap size.
Sets a target value for desired maximum pause time. The default value is 200 milliseconds. The specified value does not adapt to your heap size.
Sets the value of the STW worker threads. Sets the value of n to the number of logical processors. The value of n is the same as the number of logical processors up to a value of 8.
If there are more than eight logical processors, sets the value of n to approximately 5/8 of the logical processors. This works in most cases except for larger SPARC systems where the value of n can be approximately 5/16 of the logical processors.
Sets the number of parallel marking threads. Sets n to approximately 1/4 of the number of parallel garbage collection threads ( ParallelGCThreads ).
Sets the Java heap occupancy threshold that triggers a marking cycle. The default occupancy is 45 percent of the entire Java heap.
Sets the percentage of heap that you are willing to waste. The Java HotSpot VM does not initiate the mixed garbage collection cycle when the reclaimable percentage is less than the heap waste percentage. The default is 10 percent. This setting is not available in Java HotSpot VM, build 23.
Sets the target number of mixed garbage collections after a marking cycle to collect old regions with at most G1MixedGCLIveThresholdPercent live data. The default is 8 mixed garbage collections. The goal for mixed collections is to be within this target number. This setting is not available in Java HotSpot VM, build 23.
Sets an upper limit on the number of old regions to be collected during a mixed garbage collection cycle. The default is 10 percent of the Java heap. This setting is not available in Java HotSpot VM, build 23.
Sets the percentage of reserve memory to keep free so as to reduce the risk of to-space overflows. The default is 10 percent. When you increase or decrease the percentage, make sure to adjust the total Java heap by the same amount. This setting is not available in Java HotSpot VM, build 23.
How to Unlock Experimental VM Flags
Recommendations
When you evaluate and fine-tune G1 GC, keep the following recommendations in mind:
Overflow and Exhausted Log Messages
When you see to-space overflow/exhausted messages in your logs, the G1 GC does not have enough memory for either survivor or promoted objects, or for both. The Java heap cannot expand since it is already at its max. Example messages:
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space exhausted), 0.1957310 secs]
924.897: [GC pause (G1 Evacuation Pause) (mixed) (to-space overflow), 0.1957310 secs]
To alleviate the problem, try the following adjustments:
See «Important Defaults» for a description of these options.
Humongous Objects and Humongous Allocations
For G1 GC, any object that is more than half a region size is considered a «Humongous object». Such an object is allocated directly in the old generation into «Humongous regions». These Humongous regions are a contiguous set of regions. StartsHumongous marks the start of the contiguous set and ContinuesHumongous marks the continuation of the set.
Before allocating any Humongous region, the marking threshold is checked, initiating a concurrent cycle, if necessary.
Dead Humongous objects are freed at the end of the marking cycle during the cleanup phase also during a full garbage collection cycle.
In-order to reduce copying overhead, the Humongous objects are not included in any evacuation pause. A full garbage collection cycle compacts Humongous objects in place.
Since each individual set of StartsHumongous and ContinuesHumongous regions contains just one humongous object, the space between the end of the humongous object and the end of the last region spanned by the object is unused. For objects that are just slightly larger than a multiple of the heap region size, this unused space can cause the heap to become fragmented.
Conclusion
G1 GC is a regionalized, parallel-concurrent, incremental garbage collector that provides more predictable pauses compared to other HotSpot GCs. The incremental nature lets G1 GC work with larger heaps and still provide reasonable worst-case response times. The adaptive nature of G1 GC just needs a maximum soft-real time pause-time goal along-with the desired maximum and minimum size for the Java heap on the JVM command line.
See Also
About the Author
Monica Beckwith, Principal Member of Technical Staff at Oracle, is the performance lead for the Java HotSpot VM’s Garbage First Garbage Collector. She has worked in the performance and architecture industry for over 10 years. Prior to Oracle and Sun Microsystems, Monica lead the performance effort at Spansion Inc. Monica has worked with many industry standard Java based benchmarks with a constant goal of finding opportunities for improvement in the Java HotSpot VM.
Join the Conversation
Join the Java community conversation on Facebook, Twitter, and the Oracle Java Blog!
Как правильно установить параметры G1GC для сервера с кучей 22G
Я настраиваю новый сервер JAVA, размер кучи установлен на 22G, и будет использовать алгоритм G1GC. Я прочитал все документы оракула и считаю, что это то, что нам нужно, но все же у меня есть несколько вопросов:
4> Считаете ли вы возможным в первый раз сделать все примерно правильно? Я имею в виду без переполнения памяти или исчерпаны. Или вы думаете, что нам всегда придется более тщательно настраивать параметры, чтобы несколько раз исправить ситуацию?
5> Есть еще предложения?
Это немного долго, спасибо за ваше чтение. Любая помощь будет очень признательна. Спасибо!
2 ответа
Цитирование из документа, на который вы ссылались:
Настройка, когда у вас нет (пока) представления о проблемах с производительностью, похожа на стрельбу по мишеням с завязанными глазами. Вы можете сделать вещи хуже, чем если бы вы ничего не сделали.
Наконец, «оптимальные» настройки GC будут зависеть от различных аспектов вашего приложения, вашей рабочей нагрузки и цели ваших настроек. Все, что мы могли бы предложить, было бы чисто догадкой.
Не существует идеального набора флагов GC, которые можно применять для всех приложений. Сначала мы можем попробовать значения по умолчанию и использовать инструменты (gceasy, gcviewer), чтобы проанализировать журналы GC и посмотреть, что можно улучшить в дальнейшем.
Вот мои заметки при настройке G1GC, надеюсь вы сможете найти там полезную информацию Как сборщик мусора первый сборщик мусора (G1GC) повлиял на производительность нашего бэк-энда
Проблемы с задержками, которые G1GC
Я столкнулся с продолжающимся увеличением пауз GC с алгоритмом G1GC. Задержки службы продолжают расти со временем.
Как только это произойдет, я перезапущу свою службу, и задержки вернутся к нормальной работе. Post startup, задержки снова продолжают увеличиваться с течением времени.
Во время запуска задержка службы составляет около 200 мс, но в течение 24 часов они поднимаются до 350 мс и продолжают расти линейным образом.
Увеличение латентности обслуживания соответствует увеличению показателей GarbageCollection.
Технические характеристики
Я запускаю java-приложение (JDK-8) на M4-2X больших блоках EC2 с 50 активными потоками в ящике. Сервис работает на куче 12 ГБ. Средняя латентность запроса составляет около 250 мс, а скорость входящих запросов составляет около 20 в секунду за каждый поле.
Конфигурации G1G1
GC logs
Я ищу некоторую помощь с конфигурациями GC. На основе моего чтения я планирую увеличить количество параллельных потоков до 32, установить G1HeapRegionSize на 16M и установить ConcGCThreads = 8.
GC Причины
Резюме по удержанию
Вам нужно проверить наличие утечки в приложении.
Но в G1GC может быть один параметр, который вы можете проанализировать:
Humongous Objects
В этот момент большая часть функциональности и архитектуры G1GC была сброшена, , за исключением самой большой слабости/сложности, объекта Humongous. Как упоминалось ранее, любое выделение данных ≥ G1HeapRegionSize/2 считается объектом Humongous, который выделяется из смежных областей свободного пространства, которые затем добавляются к Tenured. Пусть пробегут некоторые основные характеристики и как они влияют на обычный жизненный цикл GC. Следующее обсуждение объектов Humongous даст представление о недостатках объектов Humongous, таких как:
Любые объекты выделяются из свободного пространства. Сбой распределения вызывает события GC. Если сбой распределения из Free space запускает GC, GC-событие будет Full GC, что очень нежелательно в большинстве случаев. Чтобы избежать полномасштабных событий GC в приложении с большим количеством объектов Humongous, необходимо обеспечить, чтобы пул свободного пространства был достаточно большим по сравнению с Eden, который Eden всегда будет заполнять первым. Обычно обычно оказывается слишком осторожным, и приложение заканчивается в состоянии, когда Free ram пул достаточно велик и никогда не используется полностью, что по определению направляет RAM.
Любые объекты освобождаются в конце MPCMC
До тех пор, пока вокруг Oracle JDK 8u45, было правдой, что объекты Humongous собирались только в конце прогонов MPCMC. В примечаниях к выпуску для версий Oracle 8u45-8u65 есть несколько коммитов, указывающих на некоторые, но не все, объекты Humongous собираются во время событий Minor.
Итак, вы можете попробовать, обновив последнюю версию java.
Собственные объекты, которые собираются только в конце MPCMC, увеличат требования к зарезервированному свободному пространству или, скорее всего, вызовут полный GC.
Поиск того, как много гуманного объекта:
Шаг 1. выполните следующую команду на вашем gc.log
grep «source: concurrent humongous allocation» /tmp/gc.log | sed ‘s/.*allocation request: \(8*\) bytes.*/\1/’ > humoungous_humongoud_size.txt
Он предоставит вам размер огромных объектов, сгенерированных в моем приложении.
Но, наконец, если ваше приложение имеет утечки памяти, вы должны решить это.
GC easy – Universal Java GC Log Analyser
Simple & effective G1 GC tuning tips
G1 GC is an adaptive garbage collection algorithm that has become the default GC algorithm since Java 9. We would like to share a few tips to tune G1 Garbage collector to obtain optimal performance.
1. Maximum GC Pause time
Consider passing ‘-XX:MaxGCPauseMillis’ argument with your preferred pause time goal. This argument sets a target value for maximum pause time. G1 GC algorithm tries it’s best to reach this goal.
2. Avoid setting young gen size
3. Remove old arguments
When you are moving from other GC algorithms (CMS, Parallel, …) to G1 GC algorithm, remove all the JVM arguments related to the old GC algorithm. Typically passing old GC algorithms arguments to G1 will have no effect, or it can even respond in a negative way.
4. Eliminating String duplicates
5. Understand default settings
For tuning purposes, in the below table, we have summarized important G1 GC algorithm arguments and their default values:
G1 GC argument | Description |
---|---|
-XX:MaxGCPauseMillis=200 | Sets a maximum pause time value. The default value is 200 milliseconds. |
-XX:G1HeapRegionSize=n | Sets the size of a G1 region. The value has to be power of two i.e. 256, 512, 1024,…. It can range from 1MB to 32MB. |
-XX:GCTimeRatio=12 | Sets the total target time that should be spent on GC vs total time to be spent on processing customer transactions. The actual formula for determining the target GC time is [1 / (1 + GCTimeRatio)]. Default value 12 indicates target GC time to be [1 / (1 + 12)] i.e. 7.69%. It means JVM can spend 7.69% of its time in GC activity and remaining 92.3% should be spent in processing customer activity. |
-XX:ParallelGCThreads=n | Sets the number of the Stop-the-world worker threads. If there are less than or equal to 8 logical processors then sets the value of n to the number of logical processors. Say if your server 5 logical processors then sets n to 5. If there are more than eight logical processors, set the value of n to approximately 5/8 of the logical processors. This works in most cases except for larger SPARC systems where the value of n can be approximately 5/16 of the logical processors. |
-XX:ConcGCThreads=n | Sets the number of parallel marking threads. Sets n to approximately 1/4 of the number of parallel garbage collection threads (ParallelGCThreads). |
-XX:InitiatingHeapOccupancyPercent=45 | GC marking cycles are triggered when heap’s usage goes beyond this percentage. The default value is 45%. |
-XX:G1NewSizePercent=5 | Sets the percentage of the heap to use as the minimum for the young generation size. The default value is 5 percent of your Java heap. |
-XX:G1MaxNewSizePercent=60 | Sets the percentage of the heap size to use as the maximum for young generation size. The default value is 60 percent of your Java heap. |
-XX:G1OldCSetRegionThresholdPercent=10 | Sets an upper limit on the number of old regions to be collected during a mixed garbage collection cycle. The default is 10 percent of the Java heap. |
-XX:G1ReservePercent=10 | Sets the percentage of reserve memory to keep free. The default is 10 percent. G1 Garbage collectors will try to keep 10% of the heap to be free always. |
6. Study GC Causes
One of the effective ways to optimize G1 GC performance is to study the causes triggering the GC and provide solutions to reduce them. Here are the steps to study the GC causes.
1. Enable GC log in your application. It can be enabled by passing following JVM arguments to your application during startup time:
From Java 9 and above:
Fig: G1 GC causes (excerpt from GCeasy report)
Below are the solutions to address each of them.
6.1. Full GC – Allocation Failure
Full GC – Allocation failures happen for two reasons:
Here are the potential solutions to address this problem:
6.2. G1 Evacuation Pause or Evacuation Failure
When you see G1 Evacuation pause, then G1 GC does not have enough memory for either survivor or promoted objects or both. The Java heap cannot expand since it is already at its max. Below are the potential solutions to fix this problem:
6.3. G1 Humongous Allocation
Any object that is more than half a region size is considered a “Humongous object”. If the regions contain humongous objects, space between the last humongous object in the region and the end of the region will be unused. If there are multiple such humongous objects, this unused space can cause the heap to become fragmented. Heap fragmentation is detrimental to application performance. If you see several Humongous allocations, please increase your ‘-XX:G1HeapRegionSize’. The value will be a power of 2 and can range from 1MB to 32MB.
6.4. System.gc()
When ‘System.gc()’ or ‘Runtime.getRuntime().gc()’ API calls are invoked from your application, stop-the-world Full GC events will be triggered. You can fix this problem through following solutions:
a. Search & Replace
This might be a traditional method :-), but it works. Search in your application code base for ‘System.gc()’ and ‘Runtime.getRuntime().gc()’. If you see a match, then remove it. This solution will work if ‘System.gc()’ is invoked from your application source code. If ‘System.gc()’ is going to be invoked from your 3rd party libraries, frameworks, or through external sources then this solution will not work. In such circumstance, you can consider using the option outlined in #b and #c.
You can forcefully disable System.gc() calls by passing the JVM argument –‘XX:+DisableExplicitGC’ when you launch the application. This option will silence all the ‘System.gc()’ calls that are invoked from your application stack.
You can pass ‘-XX:+ExplicitGCInvokesConcurrent’ JVM argument. When this argument is passed, GC collections run concurrently along with application threads to reduce the lengthy pause time.
d. RMI
If your application is using RMI, you can control the frequency in which ‘System.gc()’ calls are made. This frequency can be configured using the following JVM arguments when you launch the application:
The default value for these properties in
JDK 1.4.2 and 5.0 is 60000 milliseconds (i.e. 60 seconds)
JDK 6 and later release is 3600000 milliseconds (i.e. 60 minutes)
You might want to set these properties to a very high value so that it can minimize the impact.
6.5 Heap Dump Initiated GC
‘Heap dump Initiated GC’ indicates that heap dump was captured from the application using tools like jcmd, jmap, profilers,… Before capturing the heap dump, these tools typically trigger full GC, which will cause long pauses.. We shouldn’t be capturing heap dumps unless there is absolute necessity.
Conclusion
We hope you find this article useful. Best wishes to tune your application to get optimal performance.
Алгоритм работы CMS GC, G1 GC. Часть 2.
И на закуску, приглашаю на сцену CMS GC, и его усовершенствованного брата G1.
В этой статье мы рассмотрим два инкрементальных сборщиков мусора CMS и G1, которые нацелены на уменьшение времени SWT пауз, и увеличить производительность для работы с большими объемами в памяти. Но как мы знаем по треугольнику оптимизации, уменьшая время SWT пауз в данном случае жертвовать придется пропускной способностью. Каждый из сборщиков добивается производительности по разному, давайте посмотрим как.
CMS GC
Принципы работы
В младшем поколении работает все тот же minor цикл, а со старшим поколением работает так называемый major цикл(не путать с полным циклом), который нацелен на оперирование только старшим поколением. К тому же Tunered поколению не обязательно быть до конца заполненным, что бы запустился major цикл, вся работа происходит во время работающего приложения.
Давайте детально рассмотрим это цикл.
Начинается все с короткой остановки программы для пометки так называемых корневых объектов. После клиентская программа возобновляется, и параллельно с ней запускается один(несколько) потоков, который индексирует живые объекты используя корневые точки.
Конечно куча не постоянна, и за время работы программы, некоторые индексы стали не актуальны, поэтому происходит еще одна остановка, для повторного сканирования/индексирования объектов.
После программа возобновляется и сборщик производит очистку памяти от мертвых объектов в нескольких параллельных потоках. Но есть один нюанс, после очистки объектов из старшего поколения, упаковка(сжатие) происходить не будет, так как это проблематично осуществить во время работающего приложения, поэтому со временем память становиться фрагментированной. В связи с этим GC должен поддерживать особый список с хранением адресов участков свободной памяти (free lists). То есть при создании нового объекта, необходимо обойти этот список, что накладывает дополнительные ресурсы. Поэтом создание объекта дорогостоящая операция данном сборщике мусора.
Так же это сборщик мусора имеет интеллект и проявляется он в сборке статистики по SWT между major и minor циклами и пытается оптимизировать их во времени (разнести), что бы предотвратить скопление пауз в одном промежутке времени.
Плюсы и минусы
Как было описано выше, это конкурирующий, инкрементальный сборщик мусора, нацеленный на минимизацию простоя приложения. Для некоторых приложений это является критическим фактором. И так как он работает в фоновом режиме, пропускная способность самого приложения немного падает, так как и приложение, и сборщик мусора, будут конкурировать за ресурсы. Так же отсутствие уплотнения(сжатия) фрагментирует память, что заставляет нас выделять больше памяти (20-30 %) для этого.
Но такой сборщик может подойти приложениям, использующим большой объем долгоживущих данных. В этом случае некоторые его недостатки опускаются.
Настройка
Те же настроки что и в Parralell GC.
G1 GC
Это самый первый конкурент CMS GC, который позиционирует себя как сборщик мусора для работы с большими кучами ( > 4Гб) для которого важна сохранность времени отклика и предсказуемость. Компания Oralce хочет выдвинуть его как стоящую замену CMS и поставить его стандартным сборщиком мусора для серверных конфигурация в 9-й версии.
Принципы работы
Первое что бросается к глаза, так это организация кучи. Здесь память разбивается на множество участков от 1-32 Мб, и каждый из этих участков можеть быть как и Edem, S-0, S-1 так и Tunered. Исключением лишь являются громадные участки (humongous), которые создаются объединением простых регионов.
Работа со старшим поколением называется смешанным циклом, и она так же отличается от CMS маленькой особенностью. В G1 существует процесс, называемый циклом пометки (marking cycle), который работает параллельно с основным приложением и составляет список живых объектов. Подобный процесс присутствует и в CMS, но немного отличается в конце.
После G1 переключается в режим смешанной сборки. Это означает, что к младшим регионам, подлежащим очистке, подселяют некоторое количество из старшего региона. Делается это для того что бы оптимизировать и уложится в заданное время сборки, а размеры подселяемых участков и их количество коррелируется статистикой собранной на предыдущих циклах. После того как GC собрал достаточно мусора, он переключается в режим малой сборки.
Может произойти ситуация, что в процессе очисти не останется памяти для винивших объектов, в таком случаи запускается полный сборщик мусора и приложение приостанавливается.
Плюсы и минусы
Цель этого сборщика мусора сделать эти сборки настолько предсказуемыми насколько возможно. Так же он решает проблему фрагментации памяти. Конечно же что бы всего этого достичь, необходимо жертвовать пропускной способность(нагрузкой на CPU). На данном этапе я думаю это достойная замена CMS для северных приложений, а так же как плацдарм для экспериментов.
Настройка
Вот мы и познакомились со всеми сборщиками мусора в виртуальной машине HotSpot. Надеюсь эти статьи пролили свет на многие аспекты работы GC а так же добавило понимая, что же там все таки твориться под капотом.
В следующей статье я расскажу, какие есть проблемы у JVM (OutOFMemory etc), как их можно решать, и какие есть способы трекинга и оптимизации JVM.