问题标签 [concurrent-mark-sweep]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
2 回答
7713 浏览

java - 在 Java CMS GC 中避免升级失败

我有一个使用 CMS 垃圾收集的 Java 应用程序,它每天都会遭受几次“ParNew(提升失败)”完整 GC(参见下面的示例)。我知道当垃圾收集在老一代中找不到足够的(连续的)空间来提升新一代的对象时,就会发生提升失败。此时,它被迫执行昂贵的 stop-the-world 完整 GC。我想避免此类事件。

我已经阅读了几篇提出可能解决方案的文章,但我想在这里澄清/巩固它们:

  1. -Xmx:增加堆大小,例如。从 2G 到 4G——在老一代中提供更多空间的简单解决方案——在我的经验中似乎工作得相当好
  2. -XX:NewRatio:增加NewRatio,例如。从 2 到 4,为了增加老年代/减少新生代——给老年代更多的空间——到目前为止我的实验似乎没有太大的影响,如果有的话
  3. -XX:PromotedPadding:增加为避免升级失败而提供的填充量——但是我找不到任何关于为这个参数提供什么值的建议——有人知道这个值的含义,默认值是什么,或者什么值尝试?
  4. -XX:CMSInitiatingOccupancyFraction -XX:+UseCMSInitiatingOccupancyOnly: 让 CMS 循环更早开始以避免老年代空间不足——我还没有尝试过这个解决方案——尝试什么值是合理的?什么是默认值?
  5. 不要在堆上分配非常大的对象:一个非常大的对象可能难以提升,因为它需要在老年代大量连续的可用空间——据我所知,这不适用于我的应用程序

如果相关,这里是我当前的 GC 选项和升级失败事件之前的日志示例。

0 投票
1 回答
447 浏览

java - 并行推广失败...是什么原因?

我正在使用 3GB 堆空间运行一个 java 程序。过了一会儿,我在 gc 日志中注意到了这一点。

申请时间:0.8263100秒

2015-03-13T07:24:49.065-0700:77177.620:[GC 前 GC:

BinaryTreeDictionary 的统计信息:


总可用空间:2960457

最大块大小:1233864

块数:393

AV。块大小:7532

树高:19

GC之前:

BinaryTreeDictionary 的统计信息:


总可用空间:0

最大块大小:0

块数:0

树高:0

77177.620:[ParNew(0:提升失败大小 = 2154)(1:提升失败大小 = 2154)(2:提升失败大小 = 2154)(3:提升失败大小 = 2154)(4:提升失败大小 = 2154)( 5:提升失败大小 = 2154)(6:提升失败大小 = 2154)(7:提升失败大小 = 2154)(8:提升失败大小 = 2154)(10:提升失败大小 = 2154)(11:提升失败大小= 2154) (12: 提升失败大小 = 2154) (13: 提升失败大小 = 2154) (14: 提升失败大小 = 2154) (15: 提升失败大小 = 2154) (16: 提升失败大小 = 2154) (17 : 提升失败大小 = 2154) (18: 提升失败大小 = 2154) (19: 提升失败大小 = 2154) (20: 提升失败大小 = 2154) (21: 提升失败大小 = 2154) (22: 提升失败大小 = 2154) (23: 提升失败大小 = 2154) (24:提升失败大小 = 2154) (25: 提升失败大小 = 2154) (26: 提升失败大小 = 2154) (27: 提升失败大小 = 2154) (提升失败): 346350K->333366K(393216K), 0.3779580 秒]77177.998 : [CMSCMS: 大块 0x00000007b7da3200

: 2156277K->1695244K(2621440K), 11.2619970 secs] 2481226K->1695244K(3014656K), [CMS Perm : 193077K->191199K(256000K)]GC后:

BinaryTreeDictionary 的统计信息:


总可用空间:118536640

最大块大小:118536640

块数:1

AV。区块大小:118536640

树高:1

GC之后:

BinaryTreeDictionary 的统计信息:


总可用空间:0

最大块大小:0

块数:0

树高:0

, 11.6404220 秒] [时间:用户=16.85 系统=0.04,实际=11.64 秒]

应用程序线程停止的总时间:11.6432380 秒

申请时间:0.0421420秒

应用程序线程停止的总时间:0.0189740 秒

由于这次 Full GC,我的程序停止了 11 秒。它导致了巨大的性能问题。问题是,人们到处都在说[促销失败=碎片化]。如果是这样,那么为什么 GC 之前的最大块大小(1233864)仍然大于所有提升失败块大小(2154)的总和。

我到处检查,但无法找到导致此问题的原因。

这里有人知道这种情况不断发生的原因吗?

0 投票
1 回答
2177 浏览

java - 如何在 linux 机器上运行在 tomcat 上的 Web 应用程序使用 JVM 参数

当部署在我的生产服务器上时,我想为我的 Web 应用程序使用与默认并行 GC 不同的垃圾收集器,该服务器将在 linux 上。

举个例子,我想为应用程序使用 Concurrent Mark Sweep GC。

现在我读到我们可以通过添加-XX:+UseConcMarkSweepGC和其他各种 JVM 参数来微调它。

因此,在使用 maven 打包我的战争时,我包含了这个额外的 JVM 参数。例子:

战争已打包,我将其部署在我的 linux 环境下运行的 tomcat 服务器上。

注意我在windows机器上打包这个war然后使用putty和winscp在linux机器上部署war

我不明白的是,这将如何确保 CMS GC 正在运行?我的意思是我不应该在我的应用程序运行的地方包含这些更改吗?

或者在打包时包含这些 JVM 参数就足够了。

如果我想包含其他各种 JVM 参数也是如此,包括在打包战争时很好,或者我们还需要在其他地方包含这些参数?

请解释。

0 投票
1 回答
524 浏览

java - CMS 收集器跟不上老一代

在一个中等繁忙的生产服务器(50 个应用线程,30% 的 CPU 利用率)上,我们看到 CMS 收集器无法跟上提升到老一代的对象的速度。

我最初的想法是这些对象显然仍然被引用,因此不符合收集条件 - 但是当 Old Gen 填充并提示串行收集时,6 GiB 中的 5.5 GiB 被回收。

Eden 空间的大小为 3 GiB,大约需要 20-30 秒才能填充足够的空间以提示年轻集合。幸存者空间使用量在 800 - 1250 MiB 之间波动,最大为 1.5 GiB(每个)。

由于旧代中的对象符合收集条件,并且服务器具有大量(明显)资源,我不明白为什么 CMS 收集器没有保持在旧代大小之上:

视觉虚拟机

什么可能导致这种情况,有什么解决方案吗?

我知道占用率,但我不明白CMSIncrementalSafetyFactor- 我已经阅读了一些 Oracle 文档,但我不知道“在计算占空比时添加 [ing] 保守主义”实际上意味着什么。 .?

备择方案

切换到并行/吞吐量收集器会产生非常低的 GC 开销(1.8%),但偶尔会留下(每天 50 次)长时间的停顿——每次完整 GC 大约 20 秒。即使进行了一些调整,这也不太可能达到我们的最大暂停目标。

在理想情况下,我们可以尝试使用 G1 收集器,但由于各种原因,我们只能使用 Java 6 JVM。

0 投票
0 回答
5303 浏览

java - 了解 CMSIncrementalMode 如何帮助应用程序

除了 CMSIncrementalMode,我有两个具有相同 GC 配置的应用程序节点。以下是 GC Viewer 的屏幕截图,适用于有和没有 CMSIncrementalMode 的应用程序。

不使用 CMSIncrementalMode 的应用程序的吞吐量显着降低,并且预清理被中止并显示消息“CMS:由于时间而中止预清理”。即使老一代中有很多空白空间,这些对象也没有提升到老一代。

我知道增量较小的并发步骤可能已经停止了 preclean 中止。但我试图理解以下内容。

  1. 为什么中止的预清理会对应用程序产生如此巨大的负面影响?还是其他原因造成了负面影响?

  2. CMSIncrementalMode 如何帮助年轻一代的次要 GC。增量模式不只是在旧的 gen 集合上吗?

  3. 为什么 ParNew 计数与 initial-mark 和 remark 不同。如果没有 CMSIncrementalMode,我会看到更多标记和备注。使用 CMSIncrementalMode,我看到了更多 ParNews。

GC 配置:

GC 查看器统计信息:
应用程序使用 CMSIncrementalMode
应用程序不使用 CMSIncrementalMode

提前致谢

0 投票
1 回答
587 浏览

garbage-collection - 高数量的 CMS 标记备注暂停即使老一代不是半满

我试图了解大量 CMS 标记和评论(其他阶段也是如此)平均大约 700 毫秒的原因,即使老一代甚至没有半满。以下是来自 GCViewer 的 GC 配置和统计信息。

使用 GC 查看器的摘要:http: //i.imgur.com/0IIbNUr.png

GC 日志

0 投票
1 回答
307 浏览

java - 并发标记和扫描算法

以下是我对并发标记和扫描算法的阅读和理解

1)在初始标记中,GC根对象被标记为活动的。在这个阶段,应用程序的所有线程都被挂起。

2)并发标记时,遍历标记的根对象,标记所有可达的对象。此阶段与应用程序执行完全并发,因此所有应用程序线程都处于活动状态,甚至可以分配新对象。由于这个原因,可能会有另一个阶段标记在并发标记期间已分配的对象。这有时被称为预清理,并且仍然与应用程序执行同时进行。

3) 在最后的标记中,所有线程都被挂起,并且所有剩余的新分配的对象都被标记为活动的。

问题: 由于该算法有一个最终标记阶段,在此期间应用程序线程被挂起,那么与并行 GC 相比,该算法如何更快?

0 投票
1 回答
1047 浏览

java - Java 8:即使指定了 CMSInitiatingOccupancyFraction,CMS 也不会为老年代启动

我正在使用 tomcat7 和 JRE 1.8 运行 Java WebApp。该应用程序缓存大量数据(~15GB),并支持高吞吐量(~4K/sec)。由于请求率高,它在年轻代中产生了大量的对象,一些对象在年轻代的 ParNew 集合中存活下来,并被移动到幸存者,最终移动到堆内存中的老年代空间。

这些对象在老年代不断积累。CMS 会在老年代快满时启动,这会导致 stop-the-world GC。这会影响我的应用程序的延迟。

为了避免这种情况,我开始使用CMSInitiatingOccupancyFraction=85with +UseCMSInitiatingOccupancyOnly。然而,尽管有这两个选项,CMS 不会在老年代满 85% 时启动。当老年代快满了并且进行了一次stop-the-world GC时,它仍然会发生。我搜索了 的限制CMSInitiatingOccupancyFraction,但找不到任何解释该行为的相关链接。请在下面找到我的 tomcat 进程的确切命令行:

有人可以帮我理解为什么当老一代已满 85% 时 CMS 不开始运行吗?

0 投票
2 回答
199 浏览

java - java GC算法微调:CMS算法单独和组合

目前我正在使用 CMS 和 ParNewGC 的组合

据我了解,CMS 用于 Old Gen GC,而 UserPareNewGC 用于您的垃圾回收。

如果我只将 CMS 作为单个参数传递 -XX:+UseConcMarkSweepGCCMS 是否用于年轻一代和老一代的垃圾收集?

我认为它UseParNewGC仍然用于年轻一代,即使它没有与 CMS 一起配置。但我想确认这个假设。

我对吗?

编辑:我使用的是JDK 1.7 版本如果1.7 和 1.8中的行为不同,请解释。

0 投票
4 回答
4627 浏览

java - 为什么并发标记和清除 (CMS) 没有清理与 Full GC 相同的内存量?

我的一台生产机器有一个奇怪的问题。它托管了一个执行 CMS(并发标记和扫描)的 Java 应用程序,但它只清理了老一代的一小部分。我怀疑内存泄漏并尝试了堆转储。但是堆转储之前的 Full GC 几乎清理了所有的老年代。发生了什么?我从未见过 Java 垃圾收集的这种行为。通常 CMS 和 Full GC 应该收集大约相同数量的垃圾,现在 CMS 会多保留大约 10GB。

  • Java 1.7.0_75
  • Linux 美分操作系统 7

GC 日志:

同一应用程序在另一台使用 Cent OS 5、java 7 的机器上正常运行。

更新:问题仍未解决。我已经尝试了一切:更新操作系统包和内核,将 Java 更新到最新版本 Java 1.7.0_80,回滚应用程序版本,但没有成功。

我也验证了之前的 GC 日志,发现这个问题不是永远存在的。它开始于大约一个月前,在部署之后。