From JavaDebianTuning
Debian is a stable easy to maintain platform for Java Web Applications. However if you start using some caching frameworks, you may need to do some JVM tuning and here's the information you need to know.
Read this and to the point where you understand that a 32-process on Linux only has 2GB of addressible space. In fact, back in 1999, Linus decreed that 32-bit Linux would never, ever support more than 2GB of memory. "This is not negotiable."
Stacks are memory chunks used for saving variables and passing parameters when calling functions. It's a low level implementation detail, but the important thing to know is that each thread in each process must have it's own stack. Big stacks add up quickly as in the case of tomcat and most web servers where many threads are used to serve requests. Stacks for threads all come out of the same address space, so if you only used memory for stacks of threads you could have 1024 threads with 2MB stacks. In fact in Debian Sarge, there is no way to reduce the amount of memory allocated for the stack of a thread. [1] [2] [3] . Understand that this is not java specific, the same limitation applies to c programs.
Now that we have some fundamental stuff down, it's easy from here. Say you have 2G of Memory and want to use as much memory as possible for your cash for performance considerations. The objects in the cash will be stored in the heap memory. I think you should calculate how much memory you should use with the following formula.
HeapMemory = ProcessAdressSpace - ThreadMemory - PermGen - JVM
If you're running 32-bit, you can only see 2G max.
ProcessAdressSpace = 2G
If you web app is like mine, you'll need 100 threads. Have some librarys that may create threads, tack on another 100 to be safe. 200 threads X 2Mb/Thread = 400M
ThreadMemory = 400M
PermGen is where your defined classes go. Since you use alot of frameworks and have lots of classes, you should set this to 128M
PermGen = 128M
JVM is relatively small, but you need to give it room so that it can work quickly.
JVM = 256M
With those parameters, HeapMemory should not exceed 1264M! Anything more and you're going to slow down your application more than the cache is speeding it up, or you'll introduce nasty a OutOfMemoryException that will drive you crazy. Here's the parameters you want to use.
java -Xmx1264M -XX:MaxPermSize=128m ...
If you upgrade to etch, and set the stack size to 1MB (not recommending without extensive testing), then you can reclaim another 200MB for the heap.
java -Xmx1464M -XX:MaxPermSize=128m -Xss1M ...
You can test your deployment platform and play with the parameters with this java program.
public class ThreadLimit extends Thread { private static boolean stop = false; public void run() { try { int x = 0; while (true) { x++; Thread.sleep(100); if (stop) return; } } catch (InterruptedException e) { throw new RuntimeException(e); } } public static void main(String[] argv) throws InterruptedException { long threads = 0; try { while (true) { Thread t = new ThreadLimit(); t.start(); threads++; } } catch (Error e) { stop = true; System.out.println("Died with "+threads+" threads."); } } }
[#1] pthread_attr_setstacksize is called from jdk1.6.0 (rc1) src/launcher/java_md.c :1735
[#2] http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html#E (see question E.5) - Only LinuxThreads .8 has the ability to reset the stack size using pthread_attr_setstacksize.
[#3] cat /usr/share/doc/libc6/README.linuxthreads.gz | gunzip | more - that's right, Sarge comes with .7.
Links
- http://www.xman.org/jlinux/server.html
- http://www.caucho.com/resin-3.0/performance/jvm-tuning.xtp
- http://readlist.com/lists/tomcat.apache.org/users/3/19056.html