最大1TBのJava)を提供できるクラスターコンピューティング環境(CentOSリリース6.2Finalを実行しているIBMLSF)でRAMアプリケーションを実行しようとしています。スペース。
最大300GBの最大メモリ(Xmx)でJVMを作成できましたが、それ以上が必要です(必要に応じて詳細を提供できます)。
ただし、Xmxオプションを使用して最大メモリが300GBを超えるJVMを作成することは不可能のようです。具体的には、古典的なエラーメッセージが表示されます。
VMの初期化中にエラーが発生しました。
オブジェクトヒープ用に十分なスペースを予約できませんでした。
私の(64ビット)JVMの詳細は以下のとおりです。
OpenJDKランタイム環境(IcedTea6 1.10.6)(rhel-1.43.1.10.6.el6_2-x86_64)
OpenJDK64ビットサーバーVM(ビルド20.0-b11、混合モード)
Java 7 64ビットJVMでも試しましたが、まったく同じ問題が発生しました。
さらに、HelloWorld.jarを実行するためにJVMを作成しようとしましたが、-Xmx300Gを超える値を要求すると、JVMの作成が失敗するため、特定のアプリケーションとは関係がないと思います。
最大メモリが300Gを超えるJVMを作成できない理由を誰かが知っていますか?
誰かが解決策/回避策を提案できますか?
私はいくつかの可能な説明を考えることができます:
システム上の他のアプリケーションが大量のメモリを使用しているため、現在300Gbを使用できません。
プロセスごとのメモリサイズにリソース制限がある可能性があります。これは、ulimit
を使用して確認できます。 ( このバグ によると、プロセスごとのリソース制限により、JVMによるヒープ領域の割り当てが停止するとエラーメッセージが表示されることに注意してください。)
これが「オーバーコミット」の問題である可能性もあります。例えばアプリケーションが仮想で実行されていて、他の仮想との競争が激しいためにシステム全体が需要を満たすことができない場合。
提案された他のいくつかのアイデアは(IMO)ありそうもないです:
JREを切り替えても違いが生じる可能性はほとんどありません。特定の64ビットJVMでの任意のメモリ制限について聞いたり見たりしたことはありません。
十分な連続メモリがないことが原因である可能性は低いです。確かに連続した物理メモリは必要ありません。唯一の可能性はスワップデバイス上の連続したスペースかもしれませんが、それが典型的なLinuxOSの問題であることを思い出しません。
誰かが解決策/回避策を提案できますか?
ulimit
を確認してください。
大量のメモリをmalloc
しようとする小さなCプログラムを作成し、失敗する前にどれだけのメモリを割り当てることができるかを確認します。
システム(またはハイパーバイザー)管理者に支援を求めてください。
(編集済み、スワップスペースに関する追加セクションを参照)
CentOSを使用しているため、SHMMAX
およびSHMALL
カーネル設定について説明されているのと同様の問題が発生した可能性があります ここではOracle DBの構成用 。その同じリンクの下に、正しいSHMALL
設定を取得および設定するための計算例があります。
一部のユーザーは、十分な連続メモリが利用できないとすでに報告していますが、他のユーザーは、それは無関係であると述べています。
CentOS上のJVMが連続したメモリブロックを必要とするかどうかはわかりません。 SASによると 、断片化されたメモリは、JVMが大きな最大Xmx
または開始Xms
メモリ設定で起動するのを妨げる可能性がありますが、インターネット上の他の主張はそうではないと言っています重要です。 48GBのWindowsワークステーションでその主張を証明または証明解除しようとしましたが、40GBの初期設定と最大設定でJVMを起動することができました。そのサイズの連続したブロックは利用できなかったと確信していますが、メモリ管理はOSごとに異なる可能性があるため、異なるOS上のJVMは異なる動作をする可能性があります(つまり、Windowsは通常個々のプロセスの物理アドレスを非表示にします)。
/proc/meminfo
を使用して、使用可能な最大の連続メモリブロックを見つけます。VmAllocChunk
の下の値を参照してください。 ここにガイドと説明があります すべての値の。表示される値が300GBより小さい場合は、VmAllocChunk
の値のすぐ下にある値を試してください。
ただし、通常、この数は物理的に使用可能なメモリよりも大きくなります(使用可能な仮想メモリ値であるため)、誤検知が発生する可能性があります。予約できる値ですが、使い始めると交換が必要になる場合があります。したがって、MemFree
とInactive
の値も確認する必要があります。逆に、リスト全体を見て、300GBを超えない値を確認することもできます。
300GBでメモリ制限の問題が発生したように見える理由がわかりません。しばらくの間、最大ページ数に達したのではないかと思いました。デフォルトの4kBでは、300GBは78,643,200
ページを提供します。よく知られている魔法の数字のようには見えません。たとえば、2^24
が最大の場合、16,777,216
ページ、つまり64GBが理論上の割り当て可能な最大値になります。
ただし、議論のために、より大きなページが必要であると仮定します(つまり、大容量メモリのパフォーマンスに優れているJavaアプリケーション)) このマンページを参照してください) JBossで 、これは-XX:+UseLargePages
の使用方法とkernel.shmmax
(再びあります)、vm.nr_hugepages
およびvm.huge_tlb_shm_group
の設定方法を説明しています(後者が必要かどうかはわかりません)。
他の人もこれをすでに提案しています。問題がOSではなくJVMにあることを確認するには、ストレステストを行う必要があります。使用できるツールの1つは Stresslinux です。 このチュートリアルでは 、使用できるいくつかのオプションがあります。特に興味深いのは、次のコマンドです。
stress --vm 2 --vm-bytes 300G --timeout 30s --verbose
そのコマンドが失敗した場合、またはシステムがロックされた場合は、OSがその量のメモリの使用を制限していることがわかります。成功した場合は、使用可能なメモリを使用できるようにJVMを微調整する必要があります。
内部メモリサイズが非常に大きいシステムでは、スワップスペースをほとんどまたはまったく使用しないことも珍しくありません。多くのアプリケーションでは、これは問題にならない可能性がありますが、JVMでは、スワップ可能なスワップスペースが要求されたメモリサイズよりも大きい必要があります。 このバグレポート によると、JVMはスワップスペース自体を増やそうとしますが、 this SOスレッド提案 、JVMが常にそうできるとは限りません。
したがって、現在利用可能なスワップスペースをcat /proc/swaps # free
で確認し、300GB未満の場合は、 このCentOSマンページの手順 に従ってシステムのスワップスペースを増やします。
注1: bugreport#4719001 から、使用可能なスワップスペースの連続ブロックは必要ないことを推測できます。ただし、不明な場合は、 すべてのスワップスペースを削除して再作成してください 。これにより、断片化がすべて削除されます。
注2: これ レポート0MB
スワップスペースおよびのようないくつかの投稿を見ました。 JVM。これはおそらく、JVMがスワップスペース自体を増やすという事実によるものです。それでも、問題が解決するかどうかを確認するために、手作業でスワップスペースを増やしても問題はありません。
上記のどれもあなたの質問に対するすぐに使える答えではないことを私は理解しています。 JVMを機能させるために何を試みることができるかについて、いくつかの指針が得られることを願っています。問題が現在使用しているJVMの制限であることが判明した場合は、他のJVMを試すこともできますが、これまで読んだことから、64ビットJVMに制限を課すべきではありません。
JVMの初期化時にエラーが発生するということは、問題はJVMにあるのではなく、OSが300GBのメモリの予約に準拠できないことにあると私に信じさせます。
私自身のテストでは、JVMはすべての仮想メモリにアクセスでき、使用可能な物理メモリの量を気にしないことが示されました。仮想メモリが物理メモリよりも低い場合は奇妙ですが、VmAllocChunk
設定はその方向のヒントを与えるはずです(通常ははるかに大きいです)。
FAQセクション of Java HotSpot VMを見ると、64ビットVMでは64アドレスビットしかないため、64ビットVMで動作することがわかります。最大Javaヒープサイズは、システムに存在する物理メモリとスワップスペースの量によって異なります。
理論的に計算すると、18446744073709551616 MBのメモリを使用できますが、上記の制限があります。
JVMの最大ヒープサイズを定義するには、-Xmx
コマンドを使用する必要があります。 デフォルト 、Java 64ビットで64+ 30%= 83.2MBを使用JVM。
私は自分のマシンで以下のコマンドを試しましたが、うまく機能しているように見えました。
Java -Xmx500g com.test.TestClass
最大ヒープをテラバイトで定義しようとしましたが、機能しません。
この議論 によると、LSFはノードメモリを単一の共有スペースにプールしません。あなたはそのために何か他のものを使っています。何かのドキュメントを読んでください。あなたが求めていることを実行できない可能性があるからです。特に、すべてのノードにまたがる単一の連続領域のメモリを割り当てることができない場合があります。アプリケーションはmallocを何度も呼び出すため、通常は必要ありません。しかし、JVMは、それ自体のために物事を単純化するために、mallocを1回だけ効果的に呼び出すことによって、ヒープ全体に単一の連続した領域を割り当て(または予約)したいと考えています。または、巨大な共有メモリマシンをエミュレートするために使用しているものに関連する何か他のものである可能性があります。
JVMプロセスのユーザーとしてulimit-aを実行し、カーネルが最大メモリサイズを制限していないことを確認します。 /etc/security/limit.confの編集が必要になる場合があります