问题标签 [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.
java - 在 Java CMS GC 中避免升级失败
我有一个使用 CMS 垃圾收集的 Java 应用程序,它每天都会遭受几次“ParNew(提升失败)”完整 GC(参见下面的示例)。我知道当垃圾收集在老一代中找不到足够的(连续的)空间来提升新一代的对象时,就会发生提升失败。此时,它被迫执行昂贵的 stop-the-world 完整 GC。我想避免此类事件。
我已经阅读了几篇提出可能解决方案的文章,但我想在这里澄清/巩固它们:
- -Xmx:增加堆大小,例如。从 2G 到 4G——在老一代中提供更多空间的简单解决方案——在我的经验中似乎工作得相当好
- -XX:NewRatio:增加NewRatio,例如。从 2 到 4,为了增加老年代/减少新生代——给老年代更多的空间——到目前为止我的实验似乎没有太大的影响,如果有的话
- -XX:PromotedPadding:增加为避免升级失败而提供的填充量——但是我找不到任何关于为这个参数提供什么值的建议——有人知道这个值的含义,默认值是什么,或者什么值尝试?
- -XX:CMSInitiatingOccupancyFraction -XX:+UseCMSInitiatingOccupancyOnly: 让 CMS 循环更早开始以避免老年代空间不足——我还没有尝试过这个解决方案——尝试什么值是合理的?什么是默认值?
- 不要在堆上分配非常大的对象:一个非常大的对象可能难以提升,因为它需要在老年代大量连续的可用空间——据我所知,这不适用于我的应用程序
如果相关,这里是我当前的 GC 选项和升级失败事件之前的日志示例。
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)的总和。
我到处检查,但无法找到导致此问题的原因。
这里有人知道这种情况不断发生的原因吗?
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 参数也是如此,包括在打包战争时很好,或者我们还需要在其他地方包含这些参数?
请解释。
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。
java - 了解 CMSIncrementalMode 如何帮助应用程序
除了 CMSIncrementalMode,我有两个具有相同 GC 配置的应用程序节点。以下是 GC Viewer 的屏幕截图,适用于有和没有 CMSIncrementalMode 的应用程序。
不使用 CMSIncrementalMode 的应用程序的吞吐量显着降低,并且预清理被中止并显示消息“CMS:由于时间而中止预清理”。即使老一代中有很多空白空间,这些对象也没有提升到老一代。
我知道增量较小的并发步骤可能已经停止了 preclean 中止。但我试图理解以下内容。
为什么中止的预清理会对应用程序产生如此巨大的负面影响?还是其他原因造成了负面影响?
CMSIncrementalMode 如何帮助年轻一代的次要 GC。增量模式不只是在旧的 gen 集合上吗?
为什么 ParNew 计数与 initial-mark 和 remark 不同。如果没有 CMSIncrementalMode,我会看到更多标记和备注。使用 CMSIncrementalMode,我看到了更多 ParNews。
GC 配置:
GC 查看器统计信息:
应用程序使用 CMSIncrementalMode
应用程序不使用 CMSIncrementalMode
提前致谢
garbage-collection - 高数量的 CMS 标记备注暂停即使老一代不是半满
我试图了解大量 CMS 标记和评论(其他阶段也是如此)平均大约 700 毫秒的原因,即使老一代甚至没有半满。以下是来自 GCViewer 的 GC 配置和统计信息。
使用 GC 查看器的摘要:http: //i.imgur.com/0IIbNUr.png
GC 日志
java - 并发标记和扫描算法
以下是我对并发标记和扫描算法的阅读和理解
1)在初始标记中,GC根对象被标记为活动的。在这个阶段,应用程序的所有线程都被挂起。
2)并发标记时,遍历标记的根对象,标记所有可达的对象。此阶段与应用程序执行完全并发,因此所有应用程序线程都处于活动状态,甚至可以分配新对象。由于这个原因,可能会有另一个阶段标记在并发标记期间已分配的对象。这有时被称为预清理,并且仍然与应用程序执行同时进行。
3) 在最后的标记中,所有线程都被挂起,并且所有剩余的新分配的对象都被标记为活动的。
问题: 由于该算法有一个最终标记阶段,在此期间应用程序线程被挂起,那么与并行 GC 相比,该算法如何更快?
java - Java 8:即使指定了 CMSInitiatingOccupancyFraction,CMS 也不会为老年代启动
我正在使用 tomcat7 和 JRE 1.8 运行 Java WebApp。该应用程序缓存大量数据(~15GB),并支持高吞吐量(~4K/sec)。由于请求率高,它在年轻代中产生了大量的对象,一些对象在年轻代的 ParNew 集合中存活下来,并被移动到幸存者,最终移动到堆内存中的老年代空间。
这些对象在老年代不断积累。CMS 会在老年代快满时启动,这会导致 stop-the-world GC。这会影响我的应用程序的延迟。
为了避免这种情况,我开始使用CMSInitiatingOccupancyFraction=85
with +UseCMSInitiatingOccupancyOnly
。然而,尽管有这两个选项,CMS 不会在老年代满 85% 时启动。当老年代快满了并且进行了一次stop-the-world GC时,它仍然会发生。我搜索了 的限制CMSInitiatingOccupancyFraction
,但找不到任何解释该行为的相关链接。请在下面找到我的 tomcat 进程的确切命令行:
有人可以帮我理解为什么当老一代已满 85% 时 CMS 不开始运行吗?
java - java GC算法微调:CMS算法单独和组合
目前我正在使用 CMS 和 ParNewGC 的组合
据我了解,CMS 用于 Old Gen GC,而 UserPareNewGC 用于您的垃圾回收。
如果我只将 CMS 作为单个参数传递 -XX:+UseConcMarkSweepGC
,CMS 是否用于年轻一代和老一代的垃圾收集?
我认为它UseParNewGC
仍然用于年轻一代,即使它没有与 CMS 一起配置。但我想确认这个假设。
我对吗?
编辑:我使用的是JDK 1.7 版本。如果1.7 和 1.8中的行为不同,请解释。
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 日志,发现这个问题不是永远存在的。它开始于大约一个月前,在部署之后。