I would like to ask you HOW (or IF) is possible to reduce Spring framework's RAM footprint.
I created a simple helloworld app for demonstrating the issue. There are only two classes and context.xml file:
Main
- class with main methodTest
- class used for simulating some "work" (printig Hello in endless loop)context.xml
contains only this:
<context:component-scan base-package="mypackage" />
Test class contains only metod called init
, called after construction:
@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();
}
}
I prepared two scenarios and in both of them main
method contains only one line.
In first scenario main method does this: (new Test()).init();
App works without Spring and consumes only aprox. 8MB of RAM.
In second scenario main method contains following: new ClassPathXmlApplicationContext(new String[]{"spring/context.xml"});
So the app is initialized throug Spring container and consumes aprox. 45MB of RAM !
Is there any way how to reduce (in best case completely get rid of) this extra memory ? So far I wasn't able to find any fitting solution.
I don't mind if there is the extra memory consumption on startup - this is perfectly fine, but after that, I need our app to reduce it.
(The story behind this question is a bit more complicated, but this is for me now the core problem.)
Thank you
First a few things which you may already know but are important to understand the situation: most of the memory your program uses is the JVM heap. The heap has an initial size when your program starts executing. Sometimes the JVM will ask the OS for more memory and increase the size of the heap. The JVM will also perform garbage collection, thus freeing space in the heap.
When the used heap size diminishes, memory is not necessarily released by the JVM. The oracle JVM is reluctant to do so. For example if your program uses 500 MB of ram on startup, then after garbage collection only uses 100 MB for most of its execution, you cannot assume the additional 400 MB will be given back to your OS.
Furthermore, tools like the windows task manager (and I assume unix's ps
) will display the size of all the memory that is allocated to the JVM, regardless of whether this memory is actually used or not. Tools like jvisualvm will let you see exactly how the memory is used in your java program, and in particular what amount of heap you're actually using vs. how much is allocated.
With this in mind I tested your program in the following scenarios. Note that this depends on many factors including which JVM you use, its version, and probably your OS too.
For each case I report the allocated heap size and used heap size. Here are my results:
These results are identical, so from your question I assume you already had a different environment than I did.
Using the GC reduces heap usage, but we still have the same allocated memory
This is the most important result: more memory is allocated because Spring probably needs more at some point during startup.
Conclusions:
-XX:MaxHeapFreeRatio=70
might be a start (more here http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html#PerformanceTuning )