java - 最大堆大小 xmx 如何影响 Java 中的内存分配/已用堆?

标签 java memory-management garbage-collection

A. 如果我使用 -Xmx100000m (~100GB) 执行大型模拟程序,我会看到已用堆 (~30GB) 中出现一些峰值。该峰值会增加堆大小并减少其他程序可以使用的内存。我想将堆大小限制为在没有内存异常的情况下运行程序实际需要的大小。

enter image description here

B. 如果我使用 -Xmx10000 (~10GB) 执行我的模拟程序,我可以限制使用的堆大小(~7GB)。总堆大小也较小(当然)。在 VisualVM 图中显示的程序的第一阶段(大约 16 分钟),我没有出现内存不足异常。

enter image description here

我天真地认为,如果我将 xmx 从 10GB (B) 增加到 100GB (A),那么使用的堆将保持大致相同,并且 Java 只会使用更多内存以避免内存不足异常。但是,行为似乎有所不同。我猜想 Java 这样做是为了提高性能。

对于 A 中大量使用的堆的解释可能是如果 xmx 较大,则 HashMap 的增长行为会有所不同? xmx 对负载系数有影响吗?

在存在大量小尖峰的程序阶段(例如,参见 12:06 处的 B)而不是一些大尖峰 (A),一些 java 流被处理。流处理的内存分配是否自动适应 xmx 值? (仍然有一些内存可用于在 B 中的 12:06 处产生较少的迷你尖峰。)

如果不是,A中使用堆较大的原因可能是什么?

我如何告诉 Java 在可能的情况下保持较低的已用堆(如 B 的曲线),但如果可能发生内存不足异常则占用更多内存(允许暂时切换到 A)。这可以通过调整一些垃圾收集属性来完成吗?

编辑

正如下面的答案所述,可以通过垃圾收集参数更改配置文件。应用 -Xmx100000m -XX:MaxGCPauseMillis=1000 调整来自 A 的配置文件以消耗更少的内存(使用约 20 GB)和更多的时间(约 22 分钟)。

enter image description here

最佳答案

I would like to limit the heap size to the size that is actually required to run the program without memory exceptions.

您实际上并不想这样做,因为这会使您的程序非常慢,因为仅提供与应用程序峰值足迹相当的数量意味着每次分配都会在应用程序接近最大值时触发垃圾回收。

I guess that Java works this way in order to improve performance.

确实。

JVM 有几个目标,按降序排列:

  • 暂停时间(延迟)
  • 分配吞吐量
  • 足迹

如果您想优先考虑足迹而不是其他目标,则必须放宽其他目标。

关于java - 最大堆大小 xmx 如何影响 Java 中的内存分配/已用堆?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39508771/

相关文章:

java - 使用 Java 创建 Activity 目录用户时遇到问题

java - 使用 SSPI 从运行在 Windows 上的 Java 应用程序获取 SSO

java - 获取工作日 getter

Java 线程垃圾是否收集

haskell - 让GHC做更多的GC?

java - 使用我的位置纬度经度和DB纬度经度计算距离

javascript - AngularJS:上传图像并保存在本地存储中

java - 将 JobIntentService 绑定(bind)到 Activity

objective-c - NSString 属性复制还是只读?

cassandra - nodetool gcstats "GC Reclaimed (MB)"值过高