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

3

A. 如果我使用-Xmx100000m(约100GB)运行一个大型的模拟程序,我会看到堆使用出现一些峰值(约30 GB)。这些峰值会增加堆大小并减少其他程序可以使用的内存。我想将堆大小限制在实际运行程序所需的大小,以避免内存异常。

enter image description here

B. 如果我使用-Xmx10000(约10GB)运行我的模拟程序,我能够限制堆使用大小(约7GB)。总堆大小也较小(当然)。在VisualVM图表中显示的程序第一阶段(约16分钟)中,我不会遇到内存异常。

enter image description here

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

造成A中较大使用的堆的解释可能是,如果xmx更大,哈希映射的增长行为会有所不同? xmx是否会影响负载因子?

在许多小波峰存在的程序阶段(例如B在12:06),一些Java流被处理。流处理的内存分配是否会自动适应xmx值?(仍然有一些内存可以使用,以便在B的12:06处拥有更少的小尖峰)。

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

如何告诉Java尽可能保持低的使用堆(类似于B的曲线),但如果可能发生内存不足异常,则可以取更多的内存(允许暂时切换到A)。这可以通过调整某些垃圾回收属性来完成吗?

编辑

如下答案所述,垃圾回收参数可以改变配置文件。应用-Xmx100000m -XX:MaxGCPauseMillis = 1000可以将配置文件从A适应为占用更少的内存(约20 GB使用)和更多的时间(约22分钟)。

enter image description here


我认为这与垃圾回收算法有关。每当GC发现有足够的空间可用时,它不会释放堆空间(在A情况下)。但是当GC发现空间不足时,它会执行垃圾回收程序,并在定期和短时间间隔内释放空间(在B情况下)。 - KayV
1个回答

3
我希望将堆大小限制为实际运行程序所需的大小,以避免内存异常。

你不应该这样做,因为这会使你的程序变得极其缓慢。仅提供等同于应用程序峰值占用量的数量意味着每个分配都会在应用程序接近最大值时触发垃圾回收。

我猜 Java 是这样工作的,以提高性能。

确实如此。

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

  • 暂停时间(延迟)
  • 分配吞吐量
  • 占用空间

如果您想将占用空间优先于其他目标,则必须放松其他目标。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接