Java的-Xms和-Xmx选项的速度权衡

67

考虑以下两个命令

A:

$ java -Xms10G -Xmx10G myjavacode input.txt

B:

$ java -Xms5G -Xmx5G myjavacode input.txt

我有两个问题:

  1. 由于命令A使用其参数保留更多的内存,那么A比B运行得更快吗?
  2. -Xmx-Xms如何影响程序的运行过程和输出?

你的问题是否与现实世界中的问题有关还是只是一个理论性的问题?因为如果你在64位系统中有那么多的内存,你可能考虑改变你的算法以利用它——例如将整个大的input.txt读入/映射到内存中并对其执行操作。 - akarnokd
29
这类问题的答案总是“进行基准测试并找出结果”。 - matt b
4
我向 JVM 包的维护者询问了这个问题,他说:"在 Linux 上,除非你的设置很奇怪,否则我不确定 -Xms 的作用。也许它会分配内存而不使用 MAP_NORESERVE 选项,以确保 RAM 确实存在。但我觉得这种情况很少见。" - Ondra Žižka
8个回答

166

-Xmx参数定义了JVM的堆可以达到的最大内存大小。您必须熟悉您的程序,并查看它在负载下的表现,然后相应地设置此参数。如果值过低,可能会导致OutOfMemoryExceptions或者当程序的堆内存接近最大堆大小时,性能非常差。如果您的程序正在专用服务器上运行,您可以将此参数设置更高,因为它不会影响其他程序。

-Xms参数为JVM设置初始堆内存大小。这意味着当您启动程序时,JVM将立即分配此数量的内存。如果您的程序从一开始就会消耗大量堆内存,这很有用。这避免了JVM不断增加堆内存,从而提高了性能。如果您不确定此参数是否会对您有所帮助,请不要使用它

总之,这是一个妥协,您必须仅基于您的程序的内存行为来决定。


你说过:“如果你的程序在专用服务器上运行,你可以将此参数设置得更高,因为它不会影响其他程序。” 我认为,如果我们在同一节点上运行多个进程,并且所有进程都设置了它们的Xmx参数,那么没有一个进程会去影响其他进程,因为Xmx已经为每个进程预留了内存(这些内存不能被任何其他进程使用),对吗? - emilly
你能否提供一下对于 https://dev59.com/Qpvga4cB1Zd3GeqPvQOM 和 https://dev59.com/Qpvga4cB1Zd3GeqPvQOM 这两个问题的看法呢?非常感谢! - emilly

25

这取决于你的Java程序使用的垃圾回收器。并行垃圾回收器在更大的内存设置下可能效果更好,但我对此不是专家。

一般来说,如果你有更大的内存,垃圾回收的频率就会越低,因为有很多空间可以存放垃圾。但是,当涉及到垃圾回收时,垃圾回收需要处理更多的内存,这反过来可能会更慢。


@kd304:如果我的CPU有大容量的RAM(比如10GB),并且假设这已经足够运行我的应用程序了。你的意思是,我使用Xmx/Xms参数时分配更少的内存,我的代码就会运行得更快吗? - neversaint
1
很难说,因为性能取决于很多因素。我认为你可以在内存大小和GC运行时成本之间找到平衡点。不幸的是,我不知道你可以在哪里查看你的Java版本默认使用什么类型的GC。如果你想的话,甚至可以通过命令行参数更改GC的类型。 - akarnokd
3
除非出现大量的 Full GC,否则总的 GC 时间不会随着 RAM 的增加而增加。通常担心的是大量的 RAM 可能导致长时间没有进行 Full GC,然后在最终执行延迟很长时间的 GC 时应用程序会锁定。请注意,这里的“Full GC”指的是垃圾回收器清理整个堆空间的操作。 - Michael Borgwardt
3
我会尽力进行翻译,以下是您需要翻译的内容:@Michael Borgwardt: 我认为我描述的与你的第二句话相同。 - akarnokd
9
处理器确实拥有随机存取存储器(RAM),分别被称为一级缓存和二级缓存。 - stu
显示剩余2条评论

4
我发现在某些情况下过多的内存可能会减慢程序的运行速度。
例如,我有一个基于Hibernate的转换引擎,随着负载的增加开始变得缓慢。原来每次从数据库获取对象时,Hibernate都会检查内存中永远不会再使用的对象。
解决方案是从会话中清除旧对象。
斯图尔特

3
  1. 内存分配取决于您的操作系统。如果您分配了太多的内存,可能会导致部分加载到交换空间中,这确实会很慢。
  2. 程序运行速度快慢取决于虚拟机需要处理和清理的引用。垃圾回收器不必扫描已分配的内存以查找废弃对象。它通过引用映射来知道它们的对象及其分配的内存量。因此,清除只取决于对象的大小。如果您的程序在两种情况下表现相同,则唯一的性能影响应该是在 VM 启动时,当 VM 尝试分配操作系统提供的内存并且使用交换空间时(再次导致 1)。

3
各种-Xms和-Xmx设置之间的速度权衡取决于您运行Java应用程序的应用程序和系统。它还取决于您使用的JVM和其他垃圾收集参数。这个问题已经有11年了,自那以后,JVM参数对性能的影响变得更加难以预测。因此,您可以尝试不同的值并查看对性能的影响,或者使用免费工具Optimizer Studio自动查找最佳的JVM参数值。

2
很难说内存分配会如何影响您的速度。这取决于JVM使用的垃圾收集算法。例如,如果您的垃圾收集器需要暂停执行完整收集,则如果您比实际需要多10个内存,则收集器将有10个额外的垃圾需要清理。
如果您正在使用Java 6,则可以使用jconsole(在jdk的bin目录中)连接到进程并观察收集器的行为。一般来说,收集器非常智能,您不需要进行任何调整,但如果有需要,您可以使用众多选项进一步调整收集过程。

1
> C:\java -X

-Xmixed           mixed mode execution (default)
-Xint             interpreted mode execution only
-Xbootclasspath:<directories and zip/jar files separated by ;>
                  set search path for bootstrap classes and resources
-Xbootclasspath/a:<directories and zip/jar files separated by ;>
                  append to end of bootstrap class path
-Xbootclasspath/p:<directories and zip/jar files separated by ;>
                  prepend in front of bootstrap class path
-Xnoclassgc       disable class garbage collection
-Xincgc           enable incremental garbage collection
-Xloggc:<file>    log GC status to a file with time stamps
-Xbatch           disable background compilation
-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size
-Xss<size>        set java thread stack size
-Xprof            output cpu profiling data
-Xfuture          enable strictest checks, anticipating future default
-Xrs              reduce use of OS signals by Java/VM (see documentation)
-Xcheck:jni       perform additional checks for JNI functions
-Xshare:off       do not attempt to use shared class data
-Xshare:auto      use shared class data if possible (default)
-Xshare:on        require using shared class data, otherwise fail.

"-X选项是非标准的,可能会在不事先通知的情况下更改。"
"

(复制粘贴)

"

2
不回答问题。 - neo7

1

当我在开发一个需要每个请求创建大量线程的应用程序时,这常常是我所面临的问题。

这是一个非常好的问题,有两个方面需要考虑:
1. 我的Xms和Xmx值是否应该相同
       - 大多数网站甚至Oracle文档都建议它们相同。但是,我建议在这些值之间留出10-20%的缓冲区,以便在突然高流量峰值或偶发性内存泄漏时为您的应用程序提供堆大小调整的选项。

2. 是否应该使用较低的堆大小启动我的应用程序
       - 无论您使用什么GC算法(即使是G1),大堆总是有一些权衡。目标是确定您的应用程序行为与您可以允许的堆大小之间的GC暂停的延迟和吞吐量关系。
              - 例如,如果您的应用程序有很多线程(每个线程在本地内存中具有1 MB堆栈而不是在堆中),但未占用大量对象空间,则建议将Xms值设置得较低。
              - 如果您的应用程序创建了许多对象并增加了线程数,则需要确定可以容忍这些STW暂停的Xms值。这意味着要确定您可以容忍的传入请求的最大响应时间,并相应地调整最小堆大小。

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