web-dev-qa-db-ja.com

Springのメモリフットプリントを削減する方法

SpringフレームワークのRAMフットプリント)をどのように(またはIF)削減できるかをお聞きしたいと思います。

この問題をデモンストレーションするための簡単なhelloworldアプリを作成しました。クラスとcontext.xmlファイルは2つだけです。

  • Main- mainメソッドを持つクラス
  • Test-いくつかの「作業」をシミュレートするために使用されるクラス(無限ループのprintig Hello)

_context.xml_にはこれのみが含まれます:

_<context:component-scan base-package="mypackage" />
_

テストクラスには、構築後に呼び出されるinitというメソッドのみが含まれます。

_@Component
public class Test{

    @PostConstruct
    public void init() {
        Thread t = new Thread(new Runnable() {

            @Override
            public void run() {
                try {
                    while (true) {
                        System.out.println("Hello " + Thread.currentThread().getName());
                        Thread.sleep(500);
                    }
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        });
        t.start();
    } 
}
_

2つのシナリオを用意しましたが、どちらのシナリオでもmainメソッドには1行しか含まれていません。

最初のシナリオでは、mainメソッドはこれを行います。_(new Test()).init();_アプリはSpringなしで動作し、約を消費します。 8MBのRAM。

2番目のシナリオでは、mainメソッドに次のものが含まれています。new ClassPathXmlApplicationContext(new String[]{"spring/context.xml"});したがって、アプリはSpringコンテナーを介して初期化され、約を消費します。 45MBのRAM!

この余分なメモリを減らす(最良の場合は完全に取り除く)方法はありますか?これまでのところ、適切な解決策を見つけることができませんでした。

起動時に余分なメモリ消費があるかどうかは気にしません-これはまったく問題ありませんが、その後、それを減らすためにアプリが必要です。

(この質問の背後にある話はもう少し複雑ですが、これは私にとって今や中心的な問題です。)

ありがとうございました

12
Kousalik

最初に、すでに知っているかもしれないが状況を理解するために重要ないくつかのこと:プログラムが使用するメモリのほとんどはJVMヒープです。プログラムの実行開始時のヒープの初期サイズは次のとおりです。 JVMがOSにメモリの追加を要求し、ヒープのサイズを増やす場合があります。 JVMはガベージコレクションも実行するため、ヒープ内のスペースが解放されます。

使用されるヒープサイズが減少しても、メモリは必ずしもJVMによって解放されるとは限りません。OracleJVMはそうすることを躊躇します。たとえば、プログラムが起動時に500 MBのRAMを使用する場合、ガベージコレクションがほとんどの実行に100 MBしか使用しないと、追加の400MBがOSに返されるとは限りません。

さらに、Windowsタスクマネージャー(およびunixのpsなどのツールは、このメモリが実際に使用されているかどうかjvisualvm のようなツールを使用すると、Javaプログラムでメモリがどのように使用されているか、特に実際に使用しているヒープの量と量を正確に確認できます。が割り当てられます。


これを念頭に置いて、次のシナリオでプログラムをテストしました。これは、使用するJVM、そのバージョン、そしておそらくOSなどの多くの要因に依存することに注意してください。

  • 標準Java(SE)vsSpring。
  • ガベージコレクション(GC)となし(NOGC)(jvisualvmからガベージコレクターを呼び出しました)。
  • JVM用に定義された最小ヒープサイズ(-Xmx8Mを使用)。これは、起動時に8MBのみを割り当てるようにJVMに指示します。私のシステムのデフォルトは256MBです。

いずれの場合も、割り当てられたヒープサイズと使用されたヒープサイズを報告します。これが私の結果です:

  • SE、NOGC、256M:270 MBが割り当てられ、30MBが使用されました
  • Spring、NOGC、256M:270 MBが割り当てられ、30MBが使用されました

これらの結果は同じなので、あなたの質問から、あなたはすでに私とは異なる環境を持っていたと思います。

  • SE、GC、256M:270 MBが割り当てられ、9MBが使用されました

GCを使用するとヒープの使用量が減りますが、割り当てられたメモリは同じです

  • SE、NOGC、8M:9 MBが割り当てられ、5MB未満が使用されました
  • Spring、NOGC、8M:20 MBが割り当てられ、5MB未満が使用されます

これは最も重要な結果です。Springは起動中のある時点でおそらくより多くのメモリを必要とするため、より多くのメモリが割り当てられます。

結論:

  • ヒープの使用量を減らしたい場合は、スプリングの使用はそれほど問題にはなりません。オーバーヘッドは巨大ではありません。
  • 割り当てられたメモリを削減しようとしている場合、この実験でSpringを使用する場合の価格は高くなります。ただし、デフォルトよりも頻繁にメモリを解放するようにJVMを構成することはできます。これについてはよくわかりませんが、-XX:MaxHeapFreeRatio=70などのjvmオプションが出発点になる可能性があります(詳細はこちら http://www.Oracle.com/technetwork/Java/javase/tech/vmoptions- jsp-140102.html#PerformanceTuning
32
ARRG