A. 如果我使用 -Xmx100000m (~100GB)执行一个巨大的模拟程序,我会看到使用过的堆中有一些峰值(~30 GB)。这种峰值会增加堆大小并减少其他程序可以使用的内存。我想将堆大小限制为在没有内存异常的情况下运行程序所需的实际大小。
B。如果我用 -Xmx10000 (~10GB)执行我的模拟程序,我可以限制使用的堆大小(~7 GB)。总堆大小也是(当然)。我在VisualVM数据中显示的程序的第一阶段(约16分钟)内没有内存异常。
我天真地期望,如果我将xmx从10GB(B)增加到100GB(A),那么使用的堆将保持大致相同,并且Java只会使用更多内存以避免内存不足异常。但是,行为似乎有所不同。我想Java是以这种方式工作以提高性能。
对A中大量使用堆的解释可能是,如果xmx较大,则哈希映射的增长行为会有所不同? xmx会对负载系数产生影响吗?
在存在大量迷你峰值的程序阶段(参见例如B在12:06)而不是几个大的峰值(A)处理一些java流。流处理的内存分配是否自动适应xmx值? (还剩下一些记忆,可以用来在B的12:06减少迷你尖峰。)
如果没有,A?中使用较大堆的原因可能是什么?
如果可能的话,我如何告诉Java保持使用的堆低(如B的曲线)但是如果可能发生内存不足异常(允许暂时切换到A)则需要占用更多内存。这可以通过调整一些垃圾收集属性来完成吗?
修改
如下面的答案所述,可以通过垃圾收集参数更改配置文件。应用-Xmx100000m -XX:MaxGCPauseMillis = 1000从A调整配置文件以消耗更少的内存(使用约20 GB)和更多时间(约22分钟)。
答案 0 :(得分:3)
我想将堆大小限制为在没有内存异常的情况下运行程序所需的实际大小。
您实际上并不想这样做,因为它会使您的程序极其缓慢,因为只提供与应用程序峰值占用量相当的数量意味着每个分配都会在应用程序接近最大值时触发垃圾回收。
我猜Java是以这种方式工作以提高性能的。
确实
JVM有几个目标,按降序排列:
如果你想将足迹优先于其他目标,你必须放松其他目标。
-XX:MaxGCPauseMillis=18446744073709551615
,这是并行收集器的默认设置,但G1默认为200毫秒。