Java 8 VM GC Tunning Guild Charter 9-b
第九章 G1 GC
The Garbage-First (G1) garbage collector is a server-style garbage collector, targeted for multiprocessor machines with large memories. It attempts to meet garbage collection (GC) pause time goals with high probability while achieving high throughput. Whole-heap operations, such as global marking, are performed concurrently with the application threads. This prevents interruptions proportional to heap or live-data size.
G1 GC是服务器级别的gc,适用于运行在大内存多核心机器上的程序。该gc主要目标在满足吞吐量的同时满足尽可能短的暂停时间。对堆的整体操作,比如全局标记,是和应用程序线程同时并发执行的。通过这种方式来防止对堆内存或者活动数据内存的interruption(这个interruption怎么翻译还真是费事,其实理解起来很简单,就是一种占用)。
The G1 collector achieves high performance and pause time goals through several techniques.
G1 gc使用以下技术来达到高吞吐量和短暂停时间的目标:
The heap is partitioned into a set of equally sized heap regions, each a contiguous range of virtual memory. G1 performs a concurrent global marking phase to determine the liveness of objects throughout the heap. After the marking phase completes, G1 knows which regions are mostly empty. It collects these regions first, which often yields a large amount of free space. This is why this method of garbage collection is called Garbage-First. As the name suggests, G1 concentrates its collection and compaction activity on the areas of the heap that are likely to be full of reclaimable objects, that is, garbage. G1 uses a pause prediction model to meet a user-defined pause time target and selects the number of regions to collect based on the specified pause time target.
在G1 GC管理的内存模型中,堆被划分为若干个相等大小的空间,成为“堆区域”,每个堆区域都包含一段连续的内存地址。G1执行一个和应用线程并发的全局标记活动,通过这个活动来决定堆中的对象的生存周期。在全局标记活动结束之后,G1就知道哪个区域是剩余空间最多的区域。G1将这些剩余的空间收集起来,生成出一个巨大的可使用内存空间。这就是为什么gc的回收方法被称为G1。就像名字暗示的那样,G1总是聚焦于可能充满垃圾的内存区域。G1使用暂停预测模型来满足用户定义的暂停时间目标和选择垃圾回收的区域。
G1 copies objects from one or more regions of the heap to a single region on the heap, and in the process both compacts and frees up memory. This evacuation is performed in parallel on multiprocessors to decrease pause times and increase throughput. Thus, with each garbage collection, G1 continuously works to reduce fragmentation. This is beyond the capability of both of the previous methods. CMS (Concurrent Mark Sweep) garbage collection does not do compaction. Parallel compaction performs only whole-heap compaction, which results in considerable pause times.
G1从一个或者多个堆区域拷贝对象到一个堆的单独区域,在这个过程中压缩(这个压缩可以理解为让内存变为连续存储状态,这样读取对象地址的速度会加快)和释放内存。这个evacuation(逐出)的动作在多核机器上是并发进行的(以减少暂停时间,增加吞吐量)。这样每次gc活动,G1都是持续工作的以减少分段处理的间隔。这种能力是前面几种gc方式所不具备的。CMS不会压缩内存区域。并行GC因为执行整堆的压缩操作,会导致长时间暂停。
It is important to note that G1 is not a real-time collector. It meets the set pause time target with high probability but not absolute certainty. Based on data from previous collections, G1 estimates how many regions can be collected within the target time. Thus, the collector has a reasonably accurate model of the cost of collecting the regions, and it uses this model to determine which and how many regions to collect while staying within the pause time target.
但实际上G1并不是一个实时GC。G1只能尽可能满足高性能指标但不是绝对能满足。基于前若干次的回收,G1会对在可达到目标的时间内能回收多少区域进行评估。就这样,G1 GC使用评估后的合理准确的回收耗时模型,推算有多少内存区域可以在目标时间内进行回收。
The first focus of G1 is to provide a solution for users running applications that require large heaps with limited GC latency. This means heap sizes of around 6 GB or larger, and a stable and predictable pause time below 0.5 seconds.
G1适合用于关注高堆内存使用和有限GC延迟的应用程序使用。通常堆的大小在6GB或者更高。在这种情况下,通常的暂停时间在0.5秒之内。
Applications running today with either the CMS or the with parallel compaction would benefit from switching to G1 if the application has one or more of the following traits.
运行CMS或者parallel gc的程序,如果有以下特征,那么切换为G1 GC会更为高效:
More than 50% of the Java heap is occupied with live data.
超过50%的Java堆被活动对象占据
The rate of object allocation rate or promotion varies significantly.
对象分配的频率或者对象在代之间变换的频率非常频繁
The application is experiencing undesired long garbage collection or compaction pauses (longer than 0.5 to 1 second).
应用程序有过预期之外的长GC暂停或者压缩暂停(超过0.5秒,在1秒之内。如果超过1秒就应该怀疑是不是GC的参数配置问题了)
G1 is planned as the long-term replacement for the Concurrent Mark-Sweep Collector (CMS). Comparing G1 with CMS reveals differences that make G1 a better solution. One difference is that G1 is a compacting collector. Also, G1 offers more predictable garbage collection pauses than the CMS collector, and allows users to specify desired pause targets.
G1从长期规划上讲是CMS的继任者(想想CMS的incremental模式都被废弃了)。G1的处理gc的方式比CMS更加优秀。一个重大的差别是G1是一种压缩处理gc。并且,G1 GC比CMS提供了可被预测的gc暂停,也允许用户来指定要满足的暂停指标。
As with CMS, G1 is designed for applications that require shorter GC pauses.
和CMS相比,G1的设计是为了满足应用程序更少的GC暂停时间的目标。
G1 divides the heap into fixed-sized regions (the gray boxes) as in Figure 9-1, "Heap Division by G1".
G1的内存分代管理是将堆分为固定大小的格子区域,如下图
G1 is generational in a logical sense.
G1的内存分代是逻辑分代。
A set of empty regions is designated as the logical young generation. In the figure, the young generation is light blue. Allocations are done out of that logical young generation, and when the young generation is full, that set of regions is garbage collected (a young collection).
在上图中,淡蓝色区域都是新生代(我反正没看出来哪个是淡蓝色,哪个是深蓝色)。内存的分配在新生代进行,当新生代满了,新生代内存开始进行gc。
In some cases, regions outside the set of young regions (old regions in dark blue) can be garbage collected at the same time. This is referred to as a mixed collection. In the figure, the regions being collected are marked by red boxes. The figure illustrates a mixed collection because both young regions and old regions are being collected.
在某些情况下,新生代区域之外的内存区域(深蓝色的老生代)会同时进行垃圾回收。这被称为混合回收模式。在上图中,被回收的区域被红色标注。
The garbage collection is a compacting collection that copies live objects to selected, initially empty regions. Based on the age of a surviving object, the object can be copied to a survivor region (marked by "S") or to an old region (not specifically shown). The regions marked by "H" contain humongous objects that are larger than half a region and are treated specially; see the section Humongous Objects and Humongous Allocations in Garbage-First Garbage Collector.
GC的过程是一个压缩空间的过程,将活的对象拷贝到选中的初始空区域。基于对象存货的时间,对象被拷贝到survivor区域(在上图中被标记为S),或者到一个老区域(图里没有特别标示出来)。标示为H的区域,里面放着的都是占据内存很大的对象,通常都是占据该区域50%以上的对象。
Allocation (Evacuation) Failure
分配失败
As with CMS, the G1 collector runs parts of its collection while the application continues to run and there is a risk that the application will allocate objects faster than the garbage collector can recover free space. See the section Concurrent Mode Failure in Concurrent Mark Sweep (CMS) Collector for the analogous CMS behavior. In G1, the failure (exhaustion of the Java heap) occurs while G1 is copying live data out of one region (evacuating) into another region. The copying is done to compact the live data. If a free (empty) region cannot be found during the evacuation of a region being garbage collected, then an allocation failure occurs (because there is no space to allocate the live objects from the region being evacuated) and a stop-the-world (STW) full collection is done.
和CMS GC一样,G1大部分时间回收工作是和应用程序同时进行的,那就有种风险,应用程序分配对象的速度比gc的时间要快(这种情况CMS会有Excessive GC Time and OutOfMemoryError)。在G1里面,如果G1在拷贝活对象从一个区域到另外一个区域时,内存不够,会产生Java堆内存耗尽失败。拷贝的目的就是为了压缩活动对象的空间。如果在gc移动(复制到新的地方+清空旧的区域)对象的时候发现空间不够,没法移动,那么就会产生一个分配失败的错误。一旦这个错误产生,那么一个停止所有应用程序的FULL GC就会启动执行。
Floating Garbage
游离的垃圾对象
Objects can die during a G1 collection and not be collected. G1 uses a technique called snapshot-at-the-beginning (SATB) to guarantee that all live objects are found by the garbage collector. SATB states that any object that is live at the start of the concurrent marking (a marking over the entire heap) is considered live for the purpose of the collection. SATB allows floating garbage in a way analogous to that of a CMS incremental update.
在G1回收过程的中间对象也有可能死亡(零引用)但是不被回收。G1使用叫做SATB(开端快照)的技术来确保所有的活的对象都能被gc识别出来。SATB是指在并发标记(这种标记会扫描整个堆)开始的时刻任意存活的对象,都被看做在此次回收中都是活着的。SATB允许游离的垃圾对象像CMS增量更新那样的方式存在。
Pauses
暂停
G1 pauses the application to copy live objects to new regions. These pauses can either be young collection pauses where only young regions are collected or mixed collection pauses where young and old regions are evacuated. As with CMS there is a final marking or remark pause to complete the marking while the application is stopped. Whereas CMS also had an initial marking pause, G1 does the initial marking work as part of an evacuation pause. G1 has a cleanup phase at the end of a collection which is partly STW and partly concurrent. The STW part of the cleanup phase identifies empty regions and determines old regions that are candidates for the next collection.
G1暂停应用程序从而将活的对象拷贝到新的区域。这些暂停可以是新生代的拷贝或者是新生代和老生代的混合拷贝。和CMS一样,G1有一个最终标记(final mark,或者称为remark)的暂停,以便最终完成标记动作,这个暂停会同时暂停程序的执行。但是CMS有一个初始化的标记暂停,G1的初始化标记工作却是evacuation阶段的一部分。G1在回收的最后有一个cleanup阶段,这个阶段包含STW(STOP THE WORLD,暂停程序)部分和并发部分。STW部分标识出空的区域,并确定哪些老的区域参与下一轮的回收过程。
Card Tables and Concurrent Phases
卡片表和并发阶段
If a garbage collector does not collect the entire heap (an incremental collection), the garbage collector needs to know where there are pointers from the uncollected part of the heap into the part of the heap that is being collected. This is typically for a generational garbage collector in which the uncollected part of the heap is usually the old generation, and the collected part of the heap is the young generation. The data structure for keeping this information (old generation pointers to young generation objects), is a remembered set. A card table is a particular type of remembered set. Java HotSpot VM uses an array of bytes as a card table. Each byte is referred to as a card. A card corresponds to a range of addresses in the heap. Dirtying a card means changing the value of the byte to a dirty value; a dirty value might contain a new pointer from the old generation to the young generation in the address range covered by the card.
如果一个gc不回收整个堆(增量gc),那么这个gc就需要知道尚未被回收过的堆内存指针和已经被回收过的堆内存的指针。对于分代的gc来讲,未被回收的堆的部分就是老生代,被回收的堆的部分就是新生代。维护这个指针信息的数据结构,是一个记忆集合。卡片表是这种记忆集合的一种特定实现。Java VM使用字节数组来作为卡片表。每个字节代表一张卡,一个卡负责堆里面的一段地址。一个卡改变了值意味着改变字节数组的这个元素的值。改变的值可以包含一个老生代从新生代的新指针
Processing a card means looking at the card to see if there is an old generation to young generation pointer and perhaps doing something with that information such as transferring it to another data structure.
处理一个卡意味着检查这个卡来确定是否有老生代到新生代的指针,如果有,那么接下来可能利用这个指针数据做一些数据处理工作,比如将这个指针指向新的数据结构。
G1 has concurrent marking phase which marks live objects found from the application. The concurrent marking extends from the end of a evacuation pause (where the initial marking work is done) to the remark. The concurrent cleanup phase adds regions emptied by the collection to the list of free regions and clears the remembered sets of those regions. In addition, a concurrent refinement thread runs as needed to process card table entries that have been dirtied by application writes and which may have cross region references.
G1有一个并发阶段,在这个阶段标记活动对象。这个并发标记的阶段紧跟着内存逐出阶段开始到remark结束。并发的清理阶段将清空的区域加入到已经理内存列表,并清理记忆集合。另外,一个并发的refine线程,根据需要来处理被修改的卡片表的数据。
Starting a Concurrent Collection Cycle
启动并发回收
As mentioned previously, both young and old regions are garbage collected in a mixed collection. To collect old regions, G1 does a complete marking of the live objects in the heap. Such a marking is done by a concurrent marking phase. A concurrent marking phase is started when the occupancy of the entire Java heap reaches the value of the parameter InitiatingHeapOccupancyPercent. Set the value of this parameter with the command-line option -XX:InitiatingHeapOccupancyPercent=<NN>. The default value of InitiatingHeapOccupancyPercent is 45.
上文提到,新生代和老生代的回收是混合模式一起回收的。为了回收旧的区域,G1会在堆区做一次完整的活动对象标记。这个标记过程是并发处理的。一个并发标记阶段会在整个Java堆的空间被占用到一个百份比的时候开始执行,这个百分比是由参数InitiatingHeapOccupancyPercent设定的。使用命令行参数-XX:InitiatingHeapOccupancyPercent=<NN>来设定这个百分比。默认值是45%。
Pause Time Goal
暂停时间目标
Set a pause time goal for G1 with the flag MaxGCPauseMillis. G1 uses a prediction model to decide how much garbage collection work can be done within that target pause time. At the end of a collection, G1 chooses the regions to be collected in the next collection (the collection set). The collection set will contain young regions (the sum of whose sizes determines the size of the logical young generation). It is partly through the selection of the number of young regions in the collection set that G1 exerts control over the length of the GC pauses. You can specify the size of the young generation on the command line as with the other garbage collectors, but doing so may hamper the ability of G1 to attain the target pause time. In addition to the pause time goal, you can specify the length of the time period during which the pause can occur. You can specify the minimum mutator usage with this time span (GCPauseIntervalMillis) along with the pause time goal. The default value for MaxGCPauseMillis is 200 milliseconds. The default value for GCPauseIntervalMillis (0) is the equivalent of no requirement on the time span.
使用参数MaxGCPauseMillis为G1 GC设定暂停时间目标。G1使用一个预测模型来确定垃圾回收时间的长短。在回收的末尾,G1会选择下一次回收的区域(回收集合)。回收集合将包含新生区域(该区域的总空间大小决定了逻辑上的新生代)。G1能够控制GC暂停的时长多半要归功于这种选择新生区域的能力。可以使用命令行参数来确定新生代的大小,但是这么做可能会阻碍G1达成暂停时间目标的能力。除了暂停时间目标,也可以通过命令行参数来控制暂停在多长时间内才能发生一次。使用命令行参数GCPauseIntervalMillis(默认值为0)来确定多长时间才能暂停一次。设置为0的话,意味着暂停可以随便发生。
感谢赵大神分享
posted on 2016-10-01 00:09 🌞Bob 阅读(308) 评论(0) 编辑 收藏 举报