azul zing

介绍

Java语言规范要求某种形式的自动垃圾回收来回收未使用的存储,并禁止手动分配内存。 自动垃圾回收使程序员不必担心释放不再需要的对象,否则可能会消耗大量的设计工作。 它还可以防止某些常见的错误发生,包括某些类型的内存泄漏,悬而未决的指针错误(当一块内存被释放而仍然有指向它的指针,然后使用其中一个指针时发生)和双重空闲错误(当程序尝试释放已经释放并且可能已经重新分配的内存区域时,会发生这种情况)。

虽然垃圾回收显然具有许多优点,但它确实也存在一些问题。 最重要的是,到目前为止,商业Java运行时中垃圾回收的实际实现通常在回收过程中涉及到不可预测的“暂停”。 随着Java程序的大小和复杂性的扩展,对于Java软件架构师来说,垃圾回收暂停已成为日益严重的问题。

企业Java中广泛使用的解决此问题的技术是分发程序。 这不仅可以使堆大小更小,使暂停时间更短,还可以使某些请求继续而其他请求被暂停。 但是,这越来越意味着垃圾收集器(GC)管理的工作负载无法充分利用运行它们的硬件的功能。 我们与Azul Systems的技术副总裁兼技术副总裁Gil Tene进行了交谈,他建议垃圾收集无法跟上硬件的变化。 尽管十年前512MB-1GB的堆大小被认为是相当大的,而高端商品服务器可能已经配备了1GB-2GB RAM和2核CPU,但现代商品硬件服务器通常具有大约96GB-256GB内存在具有24-48个虚拟或物理核心的系统上运行。 在一段时间内,商品硬件存储容量增加了一百倍,常用的垃圾收集堆大小仅增加了一倍。 Tene认为,垃圾收集器已经大大落后于许多大型企业应用程序的硬件和软件需求。

收集器机制

常见任务

尽管Java运行时中的垃圾收集器的实现有所不同,但是所有商业JVM和垃圾收集模式都执行一些常见且不可避免的任务。 这些常见任务包括:

  • 识别内存堆中的活动对象
  • 回收那些非活动对象(又称“死”对象)使用的资源
  • 定期重定位活动对象以创建一定数量的连续可用空间,以适应不同大小的新对象的分配–此过程称为重定位或压缩

根据收集者的特定算法,这些任务可以在单独的阶段中执行,也可以作为单个组合遍的一部分执行。 例如,常用的跟踪收集器(在商业JVM中很受欢迎,用于较早的收集)通常使用单独的Mark,Sweep和Compact阶段来执行标识,回收和重定位任务。 另一方面,常用的复制收集器(在商业JVM中很受年轻一代的欢迎)通常将在一次复制过程中执行所有三个任务(所有活动对象在被标识时都被复制到新位置)。

并行与并发

垃圾收集器可以是单线程或并行的:

  • 单线程收集器最多使用一个CPU内核来执行垃圾收集。
  • 并行收集器使用多个线程,这些线程可以同时执行收集工作,因此可以同时使用多个CPU内核

它们也可以是停止世界运行或并发运行:

  • Stop世界收集器在应用程序代码停止的情况下执行垃圾收集工作。
  • 并发收集器与程序执行同时执行垃圾收集工作,从而允许在收集完成时继续执行程序(可能使用单独的CPU内核)。与应用程序执行同时完成,但收集工作的某些部分在应用程序执行停止的情况下执行。

React灵敏

传统的“世界停止”收集器实现显然会影响应用程序的响应能力。 鲜为人知的是,“有些并发”和“大部分并发”的收集器也会出现应用程序响应时间问题,具体取决于需要暂停的处理。 应用程序响应性和可伸缩性限制通常对世界停顿期间发生的处理类型以及导致此类停顿更频繁发生的操作的类型或速率很敏感。 应用程序可能敏感的指标示例包括:

  1. 活动集大小 :堆中的活动数据量通常将确定收集器在给定周期内必须完成的工作量。 当收集器执行的操作依赖于世界停顿暂停期间堆中活动数据的数量时,应用程序的响应能力对活动集大小变得敏感。 倾向于依赖实时集合大小的操作包括标记(在Mark-Sweep,Mark-Sweep-Compact或Mark-Compact收集器中),复制(在复制收集器中)以及堆压缩期间的引用重映射(在任何压缩收集器中) )。
  2. 堆大小 :根据所使用的算法和机制,堆的总大小可以确定收集器在给定周期内必须完成的工作量。 当收集器执行依赖于堆中内存量的操作(无论内容是活动的还是死的),并且这些操作在世界停止事件期间执行时,应用程序的响应度对堆大小变得敏感。 倾向于依赖堆大小的操作是清除(在Mark-Sweep和Mark-Sweep-Compact中)收集器。
  3. 碎片和压缩 :碎片是不可避免的,因此压缩也是如此。 当您分配对象并且其中一些对象死亡时,堆会在其中形成“洞”,这些洞对于某些对象而言足够大,而对于其他对象而言则不足。 随着时间的流逝,您会得到更多,更小的洞。 最终,您将达到堆中有足够空间的地方,但是对于某些对象而言,它没有比最大可用Kong大的空间,因此需要压缩以保持应用程序运行。 压缩将重新定位堆中的至少一些活动对象,以释放一些连续的空间以供进一步分配。 在压缩过程中将活动对象重定位到新位置时,必须跟踪并重新映射所有对重定位对象的引用,以指向新位置。 所有商业JVM都包含用于压缩堆的代码,否则,随着时间的推移,堆将变得无用。 JRockit , HotSpot和J9 JVM的所有收集器模式(并发与否)仅在停止世界的暂停期间执行压缩。 压缩暂停通常是应用程序在正常操作期间将经历的最长的暂停,因此这些收集器对堆碎片和堆大小很敏感。
  4. 变异率 :定义为程序更新内存中引用的速度,即堆,尤其是堆中对象之间的指针的改变速度。 变异率通常与应用程序负载成线性关系。 每秒执行的操作越多,对堆中的引用进行的突变就越多。 因此,如果收集器只能在暂停中标记变异的引用,或者如果并发的收集器必须在扫描阶段完成之前重复访问变异的引用,则收集器对负载很敏感,并且较高的突变率可能导致大量应用程序暂停。
  5. 弱引用或软引用的数量 :某些收集器,包括Hotspot中流行的CMS和ParallelGC收集器,仅在停止时暂停处理弱引用或软引用。 因此,暂停时间对应用程序使用的弱引用或软引用的数量敏感。
  6. 对象生存期 :大多数分配的对象都死于年轻对象,因此收藏家经常区分年轻对象和旧对象。 分代的收集器从长期存在的对象中收集最近分配的对象。 许多收藏家使用不同的算法来处理年轻一代和老一代,例如,他们可能能够一次压缩整个年轻一代,但需要更长的时间才能处理老一代。 但是,许多应用程序具有长寿命的数据集,并且这些数据集的大部分不是静态的(例如,缓存是企业系统中非常常见的模式)。 世代假设是有效的过滤器,但是如果收集旧对象比较耗时,则收集器会对对象生存期变得敏感。

考虑到应用程序响应时间的重要性,显然需要并发收集器对应用程序行为指标表现出更少的敏感性。 但是,生产系统中使用最广泛的收集器通常无法实现这些目标。

根据Tene的说法, Zing平台中包含的Azul GPGC收集器被设计为对许多这些指标不敏感,并在很宽的工作范围内保持稳定。 通过使用有保证的单程标记,收集器对突变率完全不敏感。 通过对整个堆进行并发压缩,收集器对碎片不敏感。 通过同时执行弱,软和最终参考处理,使收集器对应用程序对此类功能的使用不敏感。 通过使用快速释放功能,并通过负载值屏障的自愈特性,收集器避免了“急于完成”操作阶段的敏感性,因为它担心效率会降低,或者担心可能无法完成一个阶段或无法取得进展,而又无法回到停下来的停顿状态。 在以下各节中,我们将通过比较Azul的方法和其他常用的收集器算法来探索如何实现这一点。

Azul垃圾收集器

Azul的GPGC [ 1 ]收集器(代表“世代无中断垃圾收集器”)包含在其基于HotSpot的JVM中,具有并行和并发功能。 GPGC已经在许多生产系统中广泛使用了几年,并且已经成功地消除了或显着降低了对通常导致其他同时发生的收集器暂停的因素的敏感性。 Azul GPGC收集器专门设计为不敏感的因素包括碎片,分配率,突变率,使用软引用或弱引用以及堆拓扑。 泰恩(Tene)解释说,尽管GPGC是世代相传的收藏家,但这主要是效率的衡量标准。 GPGC对新世代和旧世代都使用相同的GC机制,这两种机制可以同时工作并压缩。 最重要的是,GPGC没有世界末日的退路。 所有压缩都与正在运行的应用程序同时执行。

根据Tene所说,算法设计的中心主题是没有“急于完成任何给定阶段”的想法。 没有任何阶段会给变种器带来很大的负担,需要通过快速结束阶段来减轻这些负担。 在收集可以再次开始之前没有完成任何阶段的“竞赛”-重定位连续运行并且可以在任何时候立即释放内存。 此外,由于所有阶段都是并行的,因此只需添加更多GC线程,GC就可以跟上任何数量的mutator线程。

负载价值壁垒

GPGC设计的核心是,收集器使用Tene所谓的“加载值屏障”,这是一种读取屏障,可在从内存中加载对象引用的值时对其进行测试,并强制执行键收集器不变式。 加载值屏障(LVB)有效地确保了所有引用在变种者看到之前都是“健全”的,而这种有力的保证是算法相对简单的原因。

加载的值障碍对所有应用程序可见的引用强制执行两个关键质量:

  1. 如果标记阶段正在进行中,则参考状态表示已被“标记通过”。 (请参见下面的标记阶段说明)。
  2. 该引用未指向已重定位的对象。

如果不满足以上任何一个条件,则加载的值屏障将触发“陷阱条件”,并且收集器将在应用程序代码不可见之前校正参考值,使其遵循所需的不变式。 结合使用负载值障碍测试和自我修复陷阱(请参见下文)可确保安全的单遍标记,从而消除了应用程序线程导致实时引用逃脱收集器访问范围的可能性。 相同的屏障和陷阱机制组合还负责支持延迟的,按需的并发压缩(对象重定位和引用重映射),从而确保应用程序线程将始终看到对象引用的正确值,而无需等待收集器以完成压缩或重新映射。

“自我修复”

GPGC并发收集的关键是处理障碍“陷阱”条件的自我修复特性。 当加载的值障碍测试表明在应用代码继续运行之前必须更改加载的参考值时,将修改加载的参考值以及从中加载存储位置的值,以符合收集器当前不变的要求(例如,表明引用已被标记,或将引用重新映射到新的对象位置)。 通过更正源内存位置中的陷阱原因(仅对于读取屏障(例如,加载的值屏障,它会拦截源地址)),GC陷阱具有“自我修复”的效果:相同的对象引用将不要为此或其他应用程序线程重新触发其他GC陷阱。 这样可以确保标记阶段以及重定位和重映射阶段的工作量是有限且可预测的。 Azul于2005年在其第一本无间断GC算法中首次提出了“自我修复”一词,Tene认为,这种“自我修复”方面仍然是Azul收集者所独有的。

Azul在现代x86处理器上实现了与自定义Vega处理器相同的逻辑LVB测试。 在Azul的Vega硬件上,LVB测试包括参考元数据中的位字段检查,以及针对GC压缩页面的特殊虚拟内存保护。 此外,Azul的硬件支持许多快速的用户模式陷阱处理程序,以处理从内存中加载与收集器当前不变式矛盾的值并对其进行测试时触发的“慢路径”陷阱条件。 这些“慢路径”陷阱处理程序可以在少数几个时钟周期(取决于4-10个时钟周期)中输入和保留,并且由GC算法用于处理此类情况-这就是“自我修复陷阱”。 在现代的x86-64硬件上,使用执行流中的指令和对虚拟内存映射的正确操作的组合,可以获得相同的LVB效果(有关更多详细信息,请参见“ 附录A ”)。

Azul算法如何工作

如下所示,Azul算法在三个逻辑阶段中实现。

  1. 标记 :负责定期刷新标记位。
  2. 重新定位 :使用最近可用的标记位查找几乎没有实时数据的页面,重新定位和压缩这些页面并释放支持的物理内存。
  3. 重新映射 :更新(向前)堆中每个重新定位的指针。

马克相

David Bacon等人( PDF文档 )将Azul GC标记相的特征定为“精确的波前”标记,而不是SATB,并增加了读取屏障。 标记阶段引入并跟踪对象引用上的“未标记通过”(NMT)状态。 NMT状态作为每个引用中的元数据位被跟踪,并且加载的值屏障验证每个引用的状态与当前GC周期的预期NMT状态相匹配。 加载的值屏障对NMT状态施加的不变性消除了应用程序线程导致活动引用逃避收集器访问范围的可能性,从而使收集器可以确保可靠且有效的单遍标记。

在标记阶段开始时,标记的工作列表将以“根”集“启动”,该根集包括应用程序线程中的所有对象引用。 正如所有标记所共有的,根集通常包括CPU寄存器和线程堆栈中的所有引用。 运行线程通过标记自己的根集进行协作,而阻塞(或停滞)线程则由收集器的标记阶段线程并行标记。

标记算法不是使用全局的世界各地的安全点(所有应用程序线程在同一时间停止),而是使用“检查点”机制。 正如Azul 2005 VEE的“无中断GC算法”论文所述:

每个线程可以在其根集被标记(并翻转了预期的NMT)之后立即进行,但是标记阶段只有在所有线程都经过检查点之后才能继续进行。

(注意:本文不再在Azul的网站上提供)。

在对所有根集进行标记后,该算法将继续进行并行和并行标记阶段。 实时引用从工作列表中拉出,其目标对象标记为实时,并且其内部引用进行递归处理。

除了在标记工作列表的正常过程中标记者自己的线程发现的引用之外,自由运行的mutator线程还可以发现他们遇到的未将其NMT位设置为期望的“标记通过”值的引用并将它们排队从内存中加载它们时。 这样的参考负载会触发已加载的值障碍的捕获条件,此时将对有问题的参考进行排队,以确保收集器可以遍历并正确标记该参考。 因此,它的NMT值将立即固定并恢复(在原始内存位置),以表明可以认为它已正确标记,从而避免了进一步的LVB条件触发。

标记阶段继续进行,直到标记工作列表中的所有对象都用尽为止,此时所有活动对象都已遍历。 在标记阶段结束时,只有已知已死的对象才被标记为“活动”,并且所有有效引用的NMT位都设置为“标记为通过”。

值得注意的是,GPGC标记阶段还同时执行软,弱和幻像引用的处理。 这种质量使得收集器对应用程序使用的软引用或弱引用的数量相对不敏感。

重定位和重映射阶段

搬迁

重定位阶段是对象重定位和页面回收的阶段。 在此阶段,通过同时将其剩余的活动对象重新定位到其他页面,可以完全闲置带有某些无效对象的页面。 这些重新定位的对象的引用不会立即重新映射以指向新的对象位置。 相反,通过依赖于加载的值屏障施加的不变性,可以在重定位后懒惰地并发地进行引用重映射,直到完成收集器的下一个重映射阶段为止,以确保收集器不会存在需要重映射的引用。

在重定位期间,选择页面集(从最稀疏的页面开始)进行重定位和压缩。 集合中的每个页面都受到保护,以防止更改者访问,并且该页面中的所有活动对象都被复制出并重新放置到连续的压缩页面中。 跟踪重定位对象位置的转发信息将保留在原始页面之外,并发重新映射将使用该信息。

在重定位期间和之后,诱变器使用引用引用重定位对象的任何尝试都会被拦截和纠正。 mutator尝试加载此类引用将触发加载的值屏障的陷阱条件,此时将纠正陈旧的引用以指向对象的正确位置,并且将修复加载该引用的原始内存位置,以避免LVB条件的未来触发。

“快速释放”

使用Tene称为“快速释放”的功能,GPGC收集器可以立即回收内存页面资源,而无需等待重新映射完成。 通过将所有转发信息都保留在原始页面之外,收集器能够在页面内容被重新定位之后(以及重新映射完成之前)立即安全地释放物理内存。 直到不再有对该页面的陈旧引用保留在堆中之前,才可以释放压缩页面的虚拟内存空间(只有在下一个重新映射阶段结束时才可靠地为true),但是支持该页面的物理内存资源会立即被释放。重定位阶段,并根据需要在新的虚拟内存位置回收。 快速释放的物理资源用于满足新的对象分配以及收集器自己的压缩管道。 通过使用“交接”压缩和快速释放功能,将压缩一页释放的页面资源用作压缩其他页面的压缩目标,并且收集器能够在一次通过中压缩整个堆,而无需进行压缩空目标内存以压缩到。

重新映射

在重定位阶段(紧随重定位阶段)之后,GC线程通过遍历对象图并对堆中找到的每个活动引用执行加载的值屏障测试,从而完成了引用重映射。 如果发现引用指向重定位的对象,则该引用将连接以指向对象的正确位置。 重新映射阶段完成后,将不存在任何活堆引用,该活堆引用将引用受先前重定位阶段保护的页面,并且在那一刻,将释放这些页面的虚拟内存。

由于重映射阶段与标记阶段将遍历相同的活动对象图,并且由于收集器不急于完成重映射阶段,因此在实际实现中将两个逻辑阶段合并为一个阶段,称为组合标记和重映射阶段。 在每个组合的Mark-Remap阶段中,收集器将完成对上一个重定位阶段所影响的引用的重新映射,同时执行下一个重定位阶段所使用的活动对象的标记和发现。

与现有垃圾收集器的比较

HotSpot的并发标记扫描(CMS)是一个并发收集器。 它在程序执行的同时执行一些垃圾回收操作,但将某些操作留给了世界各地的长时间停顿。 Tene描述如下:

Hotspot的CMS收集器使用了一个完整的,与世隔绝的并行新一代收集器,该收集器每次通过都会压缩新一代。 由于年轻一代的收集非常有效,因此这种世界通行证通常很快完成-大约100毫秒或更短。

CMS使用OldGen的并发收集器。 它具有一个并发的多遍标记,该标记在增变器运行时标记堆,并在发生变体时对其进行跟踪。 然后重新访问这些突变并重复标记。 CMS会进行最终的“世界停止”突变标记,并在“世界停止”暂停期间处理所有弱引用和软引用。

CMS不会同时压缩。 相反,它会进行并发清除,维护一个空闲列表,并尝试满足此空闲列表中的旧一代分配。 但是,由于未压缩可用列表,因此不可避免地会分散可用空间,并且CMS会退缩到完全停止状态以压缩堆。

Oracle的实验性垃圾优先(G1)收集器(预计将作为Java 7的一部分提供)是一个增量压缩的收集器,该收集器使用快照快照(此后称为SATB)并发标记算法和世界范围内的压缩暂停在每个暂停中仅压缩堆的一部分。 G1允许用户设置暂停时间目标,并使用这些目标输入以及在其标记阶段收集的拓扑信息,以便在每次暂停中压缩有限数量的堆空间,以尝试包含那些需要在每个暂停期间进行扫描。

特内(Tene)解释说,鉴于其实验状态,现在说G1在实际应用中的表现还为时过早。 根据Tene的说法,尽管G1旨在通过CMS的碎片处理来逐步改进,但其压缩仍在完全停止运行的条件下进行,而其限制增量压缩暂停时间的能力在很大程度上取决于应用程序的特定堆拓扑和对象的关系。 当需要扫描整个堆以查找需要重新映射的引用时,具有流行对象或流行堆部分的应用程序仍然会经历世界停顿的长时间停顿,而那些长停顿(虽然频率较低)将不短于停顿的停顿。当前的CMS收集器。 正如Tene所说:

如果收集器包括在紧急情况下执行全堆扫描的代码,则该代码应在某个时刻运行,并且应用程序应期望最终会遇到这种暂停。

虽然G1试图改善确定性,但不能保证这一点。 特内解释说:

它确实允许用户设置暂停时间目标,但只会“尝试”遵循这些目标。 即使OS调度是完美的,G1也不能保证确定性,因为它包含单个压缩暂停的能力固有地对堆形状敏感。 流行对象和(更重要的是)流行堆区域(从许多其他区域引用的区域,但不一定需要具有流行的单个对象)将导致G1最终在一次暂停中执行完整的堆压缩(如果要对其进行压缩) …实际的应用程序模式(例如,缓慢搅动的LRU高速缓存会获得很大的成功)将在绝大多数堆中表现出这种堆关系,从而迫使G1在单个暂停中执行有效的完全压缩重映射扫描……

InfoQ先前的文章提供了更多的技术细节。

结论

随着Zing的推出,Azul在商品硬件上的纯软件产品中提供了无休止的垃圾收集功能,使其更加易用且易于采用。 无中断的垃圾收集可以:

  1. 允许Java实例有效利用已经可用的大量,廉价的商品硬件能力,并随着硬件的未来改进而增长。
  2. 允许架构师和开发人员在他们的设计中积极使用内存容量,将诸如大型内存,进程内缓存以及完整的内存表示形式的技术应用于新的问题集。
  3. 允许开发人员避免对当前敏感的GC系统进行精细调整和重新调整。

附录A:在现代Intel和AMD处理器上实现算法

GPGC算法最初部署在Azul的Vega系统上,并且自2005年首次商业引入以来已经发展和成熟。现在,它在Vega和x86-64体系结构中都可用。 在Vega的自定义处理器上,GPGC使用特殊的加载值屏障(LVB)指令执行屏障检查。 英特尔和AMD处理器的最新改进以及虚拟化技术使Azul能够为基于英特尔和AMD的服务器带来相同的功能。 尽管x86-64体系结构上目前不存在单周期LVB指令,但Azul使用其JIT编译器生成了语义上等效的x86指令集,并有效地将其与普通指令流进行交织。 Azul专门针对英特尔,利用了EPT(扩展页表)功能(该功能首先出现在英特尔的Xeon 55xx中,随后出现在Xeon 56xx,65xx和75xx芯片中),而AMD则使用了NPT(也称为AMD-V嵌套分页)。特征。 它与x86虚拟内存子系统一起工作,以重新映射和保护GC压缩的页面,从而达到相同的加载值屏障效果,并维持无暂停GC算法工作所需的相同算法不变式。 JIT编译器发出指令的加载值屏障指令集,并有效地交错到常规指令流中。

为了在x86上模拟“快速陷阱”,Azul注入了一系列x86指令,这些指令在加载的值屏障位置执行语义上等效的测试集和条件调用,所有这些都在热情况下使用单个条件分支。 Tene将其描述为类似于使用x86指令作为“微代码”的“ LVB”指令。

x86指令是由JIT编译器注入的,我们选择了一组操作,这些操作很好地隐藏在现代x86的4个问题中,它们是乱序的,推测性的执行管道。 (例如,现代的Nehalem内核具有128 u-op深度重排序缓冲区,具有36个预留站,并结合了Macrofusion,循环流和其他出色功能)。

可以在此处找到示例讨论。

Tene继续提供一些有关热代码如何有效使用管道的细节:

  • 由于“陷井”条件很少见(一个引用有问题的NMT + SpaceID组合或正在重定位的页码),Azul设计了该序列以使用单个条件分支来确定它不会发生。 x86处理器正确地将该单一分支预测为“不沿着分支路径行进”,并且x86处理器将继续沿热路径继续执行。
  • 由于解决分支所需的操作仅取决于寄存器和几乎总是命中高速缓存的内存访问,因此通常在处理器用完推测深度之前就已很好地解决了分支问题,从而使管道正常运行而不会出现大的停顿。
  • x86很少执行能够始终有效地填充其所有4个执行单元的语义程序代码-如果这样,它将具有0.25的CPI,并且由于内存访问和缓存未命中,CPI通常比真实应用程序中的CPI高得多实际程序逻辑所需。 当CPI为0.25时,我们做的额外操作当然会花费,但在CPI较高时,它们会很好地隐藏在管道中。 Think about it this way: adding cache hitting and register-only ops to an otherwise identical semantic operations flow becomes cheaper and cheaper the higher the CPI of the original flow is, as there is plenty of idle room in the pipe.

Appendix B: GC Testing Methodology Recommendations

During this article we've looked at the various factors such as mutation rates, soft references and object lifetime, which garbage collectors can be sensitive to. However, regardless of which GC algorithm you use, it is important to test how your application performs during interesting garbage collection events. During load testing, an inexperienced team will often tune garbage collection so that it no longer occurs. However this does not prevent it from happening in the real world.

Tene suggested specifically designing tests that can cram a few days, or several hours worth, of interesting GC events into a short but practical test length, by adding low load noise. There are several techniques which are good for this, such as background LRU caches. But one of easiest, and most effective, is a simple fragmentation generator, such as the Fragger tool which Tene wrote and which is freely available from the Azul Website .

Fragger works by repeatedly generating large sets of objects of a given size, pruning each set down to a much smaller remaining live set, and increasing the object size between passes such that it becomes unlikely to fit in the areas freed up by objects released in a previous pass without some amount of compaction. Fragger ages object sets before pruning them down in order to bypass potential artificial early compaction by young generation collectors. When run with default settings, Fragger will occupy ~25% of the total heap space, and allocate objects at a rate of 20MB/sec.

The general idea is to test the metrics we've discussed for sensitivity, and establish the range in which your application works well. To do this, vary the metrics under your control by increasing the things the application does to generate them. For example you can:

  • increase the size of state that each session or main object carries.
  • increase the lifetime of state associated with sessions or requests.
  • increase the amount of data the application caches.

By pushing these things until your application ceases to meet your performance requirements, you'll find the edges of the safe envelope inside which your application can run.

脚注

1. Since this article was first published GPGC has been renamed to C4 (Continuously Concurrent Compacting Collector). The algorithm described here is the same as that used in the C4 collector. [ << Back ]

翻译自: https://www.infoq.com/articles/azul_gc_in_detail/?topicPageSponsorship=c1246725-b0a7-43a6-9ef9-68102c8d48e1

azul zing

azul zing_Azul垃圾收集器相关推荐

  1. gc垃圾收集器 与gc算法_GC解释:收集器概述

    gc垃圾收集器 与gc算法 当前版本的HotSpot JVM包括三种类型的垃圾收集器: –串行收集器 –并行收集器 –多数同时收集者 它们都是世代的,这意味着它们利用了堆的划分方式 . 垃圾收集器负责 ...

  2. java g1 收集调优_Java性能调优:充分利用垃圾收集器

    java g1 收集调优 JVM背后发生了什么,垃圾回收如何影响Java性能? 性能调优世界是一个危险的地方,一个JVM标志失衡,事情很快就会变得繁琐. 因此 ,我们决定求助于Java性能调优专家, ...

  3. Java性能调优:充分利用垃圾收集器

    JVM背后发生了什么,垃圾回收如何影响Java性能? 性能调优世界是一个危险的地方,一个JVM标志失衡,事情很快就会变得繁琐. 因此 ,我们决定求助于Java性能调优专家, 单调 JVM探查器mjpr ...

  4. 选择合适的垃圾收集器

    HotSpot虚拟机提供了种类繁多的垃圾收集器,选择太多反而令人踌躇难决,若只挑最先进的显然不可能满足全部应用场景,但只用一句"必须因地制宜,按需选用"又未免有敷衍的嫌疑,本节我们 ...

  5. JVM学习四:垃圾收集器与内存回收策略

    一.经典垃圾收集器 如果垃圾收集算法是内存回收的方法论,那么垃圾收集器就是内存回收的实践者.<Java虚拟机规范>对于垃圾收集器的实现没有任何规定. 这里介绍的经典垃圾收集器," ...

  6. 垃圾收集器与内存分配策略系列(三)

    经典垃圾收集器 1. Serial收集器 2. ParNew收集器 3. Parallel Scavenge收集器 4. Serial Old收集器 5. Parallel Old收集器 6. CMS ...

  7. 深入理解java虚拟机(六)GC垃圾回收-低延迟垃圾收集器(Shenandoah、ZGC)

    文章目录 前言 一.Shenandoah收集器 1.Shenandoah介绍 2.Shenandoah与G1对比 3.Shenandoah工作原理 4.Shenandoah并行整理的核心概念-Broo ...

  8. 垃圾收集器G1和ZGC详解

    垃圾收集器G1和ZGC详解 1.G1(Garbage-First) 1.1.分代特性 1.2.G1回收流程 1.3.G1回收主要算法 1.3.1.G1垃圾回收算法 1.3.2.G1筛选回收筛选算法 1 ...

  9. JVM之(Shenandoah、ZGC收集器)(基于《深入理解Java虚拟机》之第三章垃圾收集器与内存分配策略)(下)

    上一篇丹丹学妹已经给我讲了七种经典的GC器,那到底怎么样的GC器才能称的上"完美"? asda这就涉及到了衡量GC器性能的三项最重要的指标:①.内存占用②.吞吐量 ③.低时延 ,有 ...

最新文章

  1. SAP MM 项目上线库存初始化导入问题 --- 进口物料在途库存之处理
  2. python免费入门教程-python入门免费教程看这些就够了
  3. 关于ThinkPHP的一些编程技巧
  4. 【鸿蒙 HarmonyOS】创建 Java 语言 HarmonyOS 手机应用 ( 首次进入 DevEco Studio 配置环境 | 创建 Java 手机工程 | 鸿蒙工程代码目录简介 )
  5. bazel 链接第三方动态库_C语言学习篇(31)——linux中制作动态链接库
  6. 网站自动登录功能的设计
  7. 第二轮“双一流”名单:这 44 所高校有调整!
  8. .net core上 K8S(七).netcore程序的服务发现
  9. 使用Java和JSF构建一个简单的CRUD应用
  10. Tomcat之Windows环境下配置多个服务器
  11. 一加屏幕检测代码_一加7Pro深度体验:亿元屏幕真曲面
  12. ivy java_Ivy 在eclipse里的配置
  13. MTK Android 修改权限读取IMEI
  14. android跳一跳作弊编程,跳一跳辅助器作弊刷分 微信跳一跳辅助工具(安卓/iOS苹果)-优基地...
  15. 坚定信念,追求自己的理想!让那些坏人去死把!!!
  16. NFS配置(RHCE考试题)
  17. 一键中文数据增强包 ; NLP数据增强、bert数据增强、EDA:pip install nlpcda
  18. MCE | 新冠 德尔塔病毒
  19. 苹果最新专利:虚拟SIM卡
  20. 内最有份量的破解下载网站一览

热门文章

  1. Linux 管道通信
  2. C#合并Excel单元格
  3. html伸缩布局,HTML-CSS:伸缩布局
  4. InputStream输入流七牛上传图片
  5. 用百度地图进行搜索周边的建筑,医院,餐厅,学校等。
  6. ROS机器人的远程启动和控制过程
  7. 解线性方程组c语言实验报告,实验五线性方程组的迭代法实验
  8. vue使用高德地图关键字搜索功能的实例代码(踩坑经验)
  9. php薄饼,厦门薄饼
  10. Node.js之npm ERR code EPERM npm ERR syscall open npm ERR