Sun/Oracle JVMの内部オーバーヘッドを減らす方法は?
質問
この問題は具体的です Linux x86-64で実行されているSun Java JVM. 。私は理解しようとしています Sun JVMがヒープと非ヒープの制限を設定したときでさえ、システムの物理的メモリの多くを取る理由.
私が実行しているプログラムは、複数のプラグイン/機能を備えたEclipse 3.7です。最も使用される機能は、PDT、EGIT、MyLynです。次のコマンドラインスイッチで日食を開始します。
-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に制限し、非HEAPに150 MBに制限する必要があります (jconsoleがラベル付けした「CMS永久生成」および「コードキャッシュ」)。論理的には、JVMは合計350 MBとJVMが必要とする内部オーバーヘッドを取る必要があります。
実際には、JVMには544.6 MBが必要です ps_mem.pyによって計算された私の現在の日食プロセスの場合(http://www.pixelbeat.org/scripts/ps_mem.py)Linux 2.6+カーネルによって予約された実際の物理メモリページを計算します。 それは35%または約200MBの内部Sun JVMのオーバーヘッドです!
このオーバーヘッドを減らす方法についてのヒントはありますか?
ここにいくつかの追加情報があります:
$ 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の非HEAPを使用しています。
Eclipseを実行するために余分な200MBを使用する余裕がないと言っているわけではありませんが、この廃棄物を減らす方法がある場合は、カーネルブロックデバイスバッファーまたはファイルキャッシュにその200MBを使用したいと思います。さらに、私は他のJavaプログラムと同様の経験を持っています - おそらく、同様の調整でそれらすべてのオーバーヘッドを減らすことができます。
更新:質問を投稿した後、以前の投稿を見つけました。ヒープなどが安定している場合でも、なぜSun JVMはRSSメモリをより多く消費し続けるのですか?使用する必要があるようです pmap
問題を調査するため。
解決
Eclipse環境の記憶消費量が高い理由は、SWTの使用だと思います。 SWTは、JVMのヒープの外に住んでいるネイティブグラフィックライブラリであり、状況を悪化させるために、Linuxの実装は実際には最適化されていません。
山の外側のメモリに関するあなたの日食環境の記憶消費を減らす機会は本当にないと思います。
他のヒント
Eclipseは記憶とCPU Hogです。 Javaクラスライブラリに加えて、すべてのローエンドGUIのものはネイティブシステムコールによって処理されるため、プロセスに添付された低レベルX用語呼び出しを実行するために、かなりの「ネイティブ」JNIライブラリがあります。
Eclipseは、何百万もの有用な機能と多くのヘルパーを提供して、日々のプログラミングタスクを高速化しますが、無駄のないことはそうではありません。メモリまたはリソースの減少は、おそらく顕著な減速につながるでしょう。それは本当にあなたがあなたの時間とあなたのコンピューターのメモリをどれだけ大切にしているかに依存します。
あなたが無駄のないgvimとmakeが無敵であることを望むなら。コードの完了、自動ビルドなどが必要な場合は、追加のリソースでこれを支払うことを期待する必要があります。
次のプログラムを実行した場合
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です。 VSZサイズにカウントされる約200 MBの共有ライブラリがあります。残りは、マックスヒープ、マックスパーマンで、スレッドスタックなどのオーバーヘッドを備えたものに注意することができます。
問題はJVMではなく、アプリケーションが実行されているようです。追加の共有ライブラリを使用すると、直接メモリとメモリマップファイルは、使用するメモリの量を増やすことができます。
約100ドルで16 GBを購入できることを考えると、これが実際に問題であることを知っていますか?