加快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位系统中有那么多RAM,那么您可能会考虑更改算法以利用它-例如,将整个大input.txt读取/映射到内存中并对其执行操作。
akarnokd

28
这些类型的问题的答案始终是“确定基准并找出答案”。
马特b 2009年

4
我问JVM软件包的维护者,他说:“在Linux上,除非您有一个怪异的设置,否则我不确定-Xms是否会起到很大作用。也许它分配时没有MAP_NORESERVE只是为了确保RAM确实存在。但是我对此表示怀疑。 。”
Ondra参观Žižka

Answers:


24

这取决于您的Java使用的GC。并行GC在较大的内存设置上可能会更好地工作-尽管我不是专家。

通常,如果您拥有更大的内存,则不需频繁对其进行GC处理-会有大量的垃圾空间。但是,当涉及到GC时,GC必须在更多的内存上工作-从而可能会变慢。


@ kd304:因此,如果我的CPU具有较大的RAM(例如10GB),可以说这足以使我的应用程序运行。您是说我们使用Xmx / Xms参数中的内存越少,代码运行得越快?
neversaint 2009年

1
很难说,因为性能取决于很多事情。我会说您可以在内存大小和GC运行时成本之间找到平衡。不幸的是,我不知道您可以在哪里检查Java版本默认的GC类型。如果需要,您甚至可以通过命令行参数更改GC的类型。
akarnokd

3
GC上花费的总时间不会随RAM的数量而增加,除非您遇到大量GC完整的病理情况。通常需要大量RAM的问题是,它可能导致长时间不执行完整的GC,随后应用程序锁定,而最终执行了已推迟了这么长时间的GC。
Michael Borgwardt

3
@Michael Borgwardt:我以为我描述的和你的第二句话是一样的。
akarnokd

9
恩 CPU确实具有随机存取存储器。这称为1级和2级缓存。
2013年

166

-Xmx参数定义堆可以为JVM达到的最大内存大小。您必须非常了解您的程序,并查看其在负载下的性能,并相应地设置此参数。如果程序的堆内存达到最大堆大小,则较低的值可能会导致OutOfMemoryExceptions或非常差的性能。如果您的程序在专用服务器上运行,则可以将此参数设置得更高一些,因为它不会影响其他程序。

-Xms参数设置JVM的初始堆内存大小。这意味着,当您启动程序时,JVM将立即分配此内存量。如果您的程序从一开始就消耗大量堆内存,这将很有用。这样可以避免JVM不断增加堆并在那里获得一些性能。如果您不知道此参数是否会对您有所帮助,请不要使用它

总而言之,这是一个折衷方案,您只能根据程序的内存行为来决定。


您说过, If your program is running in dedicated server you can set this parameter higher because it wont affect other programs我相信,如果我们在同一节点上运行多个进程,并且都设置了XMx参数,那么没有进程会像Xmx一样转到其他进程,则已经为每个进程保留了内存(任何其他进程都无法使用该内存)过程)对吗?
emilly,2016年


4

我发现在某些情况下,过多的内存可能会使程序变慢。

例如,我有一个基于休眠的转换引擎,随着负载的增加,该引擎开始缓慢运行。事实证明,每次我们从数据库中获取一个对象时,hibernate都会检查内存中是否存在将不再使用的对象。

解决方案是从会话中逐出旧对象。

斯图尔特


3
  1. 分配始终取决于您的操作系统。如果分配过多的内存,最终可能会将部分加载到交换中,这确实很慢。
  2. 程序运行速度是慢还是快取决于VM必须处理和清理的引用。GC不必遍历已分配的内存来查找废弃的对象。它知道对象以及它们通过引用映射分配的内存量。因此,扫描仅取决于对象的大小。如果您的程序在两种情况下的行为均相同,则唯一的性能影响应该是对VM启动,VM尝试分配操作系统提供的内存以及使用交换(再次导致结果为1)。

2

很难说内存分配将如何影响您的速度。这取决于JVM使用的垃圾回收算法。例如,如果您的垃圾收集器需要暂停以进行完整的收集,那么如果您的内存比实际需要多10个,则垃圾收集器还有10个要清理的垃圾。

如果使用的是Java 6,则可以使用jconsole(在jdk的bin目录中)附加到您的进程,并观察收集器的行为。通常,收集器非常聪明,您不需要进行任何调整,但是如果有需要,可以使用许多选项来进一步调整收集过程。


2

-Xms和-Xmx的各种设置之间的速度折衷取决于运行Java应用程序的应用程序和系统。它还取决于您的JVM和使用的其他垃圾回收参数。

这个问题已有11年历史了,从那时起,JVM参数对性能的影响就变得更加难以预先预测。因此,您可以尝试使用不同的值并查看对性能的影响,或者使用免费的工具(如Optimizer Studio)自动找到最佳的JVM参数值。


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选件是非标准的,如有更改,恕不另行通知。

(复制粘贴)


1
不回答问题。
neo7

1

这一直是我在一个应用程序上工作时遇到的问题,该应用程序为每个请求创建大量线程。

因此,这是一个非常好的问题,它涉及两个方面:
1.我的Xms和Xmx值是否应该相同
       -大多数网站,甚至oracle文档都建议相同。但是,我建议在这些值之间留出10%到20%的缓冲区,以便在突然的高流量高峰或偶然的内存泄漏的情况下为应用程序调整堆大小。

2.是否应该以较小的堆大小启动我的应用程序
       -这就是问题-无论您使用哪种GC算法(甚至是G1),大堆总会有一些折衷。目的是确定应用程序的行为,以使其可以在延迟和吞吐量方面允许GC暂停的堆大小为准。
              -例如,如果您的应用程序有很多线程(每个线程在本机内存中有1 MB堆栈,在堆中没有),但是不占用大量对象空间,那么我建议使用较低的Xms值。
              -如果您的应用程序创建了许多线程数量增加的对象,那么请确定可以设置Xms的值来容忍那些STW暂停。这意味着确定可以容忍的传入请求的最大响应时间,并调整最小堆大小。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.