如何减少Sun / Oracle JVM内部开销?

时间:2011-10-18 10:23:07

标签: java eclipse memory jvm overhead

此问题特别针对在Linux x86-64上运行的Sun Java JVM 。我试图找出为什么即使我设置了Heap和Non-Heap限制,Sun JVM也会占用系统的大量物理内存。

我正在运行的程序是带有多个插件/功能的Eclipse 3.7。最常用的功能是PDT,EGit和Mylyn。我使用以下命令行开关启动Eclipse:

-nosplash -vmargs -Xincgc -Xms64m -Xmx200m -XX:NewSize=8m -XX:PermSize=80m -XX:MaxPermSize=150m -XX:MaxPermHeapExpansion=10m -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -XX:+UseCMSInitiatingOccupancyOnly -XX:+UseParNewGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing -XX:CMSIncrementalDutyCycleMin=0 -XX:CMSIncrementalDutyCycle=5 -XX:GCTimeRatio=49 -XX:MaxGCPauseMillis=50 -XX:GCPauseIntervalMillis=1000 -XX:+UseCMSCompactAtFullCollection -XX:+CMSClassUnloadingEnabled -XX:+DoEscapeAnalysis -XX:+UseCompressedOops -XX:+AggressiveOpts -Dorg.eclipse.swt.internal.gtk.disablePrinting

值得注意的是特别是开关:

-Xms64m -Xmx200m -XX:NewSize=8m -XX:PermSize=80m -XX:MaxPermSize=150m

这些交换机应将JVM堆限制为最大200 MB,将非堆限制为150 MB (“CMS永久生成”和“代码缓存”,由JConsole标记)。从逻辑上讲,JVM应该总共需要350 MB加上JVM所需的内部开销。

实际上,我的当前Eclipse进程的JVM需要544.6 MB ,由ps_mem.py(http://www.pixelbeat.org/scripts/ps_mem.py)计算,它计算Linux 2.6+内核保留的实际物理内存页面。 内部Sun JVM开销为35%或大约200MB!

有关如何减少此开销的任何提示?

以下是其他一些信息:

$ ps auxw
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
me       23440  2.4 14.4 1394144 558440 ?      Sl   Oct12 210:41 /usr/bin/java ...

根据JConsole,该进程使用了​​160 MB的堆和151 MB的非堆。

我并不是说我无法负担使用额外的200MB来运行Eclipse,但是如果有办法减少浪费,我宁愿使用200MB用于内核块设备缓冲区或文件缓存。另外,我和其他Java程序有类似的经验 - 也许我可以通过类似的调整来减少所有这些程序的开销。

更新:发布问题后,我发现上一篇文章到SO: Why does the Sun JVM continue to consume ever more RSS memory even when the heap, etc sizes are stable? 我似乎应该使用pmap来调查此问题。

3 个答案:

答案 0 :(得分:3)

我认为Eclipse环境的高内存消耗的原因是使用SWT。 SWT是一个生活在JVM堆之外的本机图形库,为了使情况恶化,Linux上的实现并没有真正优化。

我认为没有机会减少eclipse环境中关于堆外部内存的内存消耗。

答案 1 :(得分:1)

Eclipse是一个内存和CPU。除了Java类库之外,所有低端GUI内容都由本机系统调用处理,因此您将拥有一个实质的“本机”JNI库来执行附加到您的进程的低级X术语调用。

Eclipse提供了数以百万计的有用功能和大量助手来加速您的日常编程任务 - 但精益而非意味着它不是。内存或资源的任何减少都可能导致明显的减速。这实际上取决于你对计算机内存的重视程度。

如果你想要精益和平均gvim和make是无与伦比的。如果你想要代码完成,自动构建等,你必须期望用额外的资源来支付。

答案 2 :(得分:0)

如果我运行以下程序

public static void main(String... args) throws InterruptedException {
    for (int i = 0; i < 60; i++) {
        System.out.println("waiting " + i);
        Thread.sleep(1000);
    }
}
带有ps auwx打印的

USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
500      13165  0.0  0.0 596680 13572 pts/2    Sl+  13:54   0:00 java -Xms64m -Xmx200m -XX:NewSize=8m -XX:PermSize=80m -XX:MaxPermSize=150m -cp . Main

使用的内存量为13.5 MB。大约200 MB的共享库计入VSZ大小。其余的可以在max heap,max perm gen中计算,其中包含线程堆栈的开销等。

问题似乎不是JVM,而是运行在其中的应用程序。使用其他共享库,直接内存和内存映射文件可以增加使用的内存量。

鉴于您可以以100美元左右的价格购买16 GB,您知道这实际上是一个问题吗?