tags:

views:

386

answers:

5

I'm running a handfull of Java Application servers that are all running the latest versions of Tomcat 6 and Sun's Java 6 on top of CentOS 5.5 Linux. Each server runs multiple instances of Tomcat.

I'm setting the -Xmx450m -XX:MaxPermSize=192m parameters to control how large the heap and permgen will grow. These settings apply to all the Tomcat instances across all of the Java Application servers, totaling about 70 Tomcat instances.

Here is a typical memory usage of one of those Tomcat instances as reported by Psi-probe

Eden           = 13M
Survivor       = 1.5M 
Perm Gen       = 122M 
Code Cache     = 19M 
Old Gen        = 390M 
Total          = 537M

CentOS however is reporting RAM usage for this particular process at 707M (according to RSS) which leaves 170M of RAM unaccounted for.

I am aware that the JVM itself and some of it's dependancy libraries must be loaded into memory so I decided to fire up pmap -d to find out their memory footprint. According to my calculations that accounts for about 17M.

Next there is the Java thread stack, which is 320k per thread on the 32 bit JVM for Linux. Again, I use Psi-probe to count the number of threads on that particular JVM and the total is 129 threads. So 129 + 320k = 42M

I've read that NIO uses memory outside of the heap, but we don't use NIO in our applications.

So here I've calculated everything that comes to (my) mind. And I've only accounted for 60M of the "missing" 170M.

What am I missing?

+1  A: 

Arnar, In JVM initialization process JVM will allocate a memory (mmap or malloc) of size specified by -Xmx and MaxPermSize,so anyways JVM will allocate 450+192=642m of heap space for application at the start of the JVM process. So java heap space for application is not 537 but its 642m.So now if you do the calculation it will give you your missing memory.Hope it helps.

Anil Vishnoi
I think you can set the initial heap with the Xms switch, and it will grow to the Xmx size only on demand.
duduamar
Yes,initially application will be given a size equal to -Xms to allocate the object,and it further grow till -Xmx as per the requirement of the application.But JVM heap is a continuous space of size -Xms + Perm size.When heap grows it will be given some more memory from this pre allocated space of size -Xmx.
Anil Vishnoi
-Xms is one parameter which will help JVM to decide when to trigger the GC,so whenever application fully occupied the heap of size -Xms,JVM will trigger the GC and it tried to clean up the garbage objects,after that if GC didn't cleaned up much space to allocate the application object request then JVM will expand the heap by certain amount.(Shrinkage and expansion is based of too many other factors aswell).
Anil Vishnoi
Thanks for you reply Anil. I just restarted the JVM in question and once it had fully initilalized the RSS memory footprint is only 273M. The JVM heap + permgen + code cache + native code size + thread stack is currently at 248M. So I don't think that the whole heap is being allocated to RSS memory. If I don't specify -Xms or -XX:PermSize the JVM sets -xms to 64mb (1/64th of available RAM, which is 4G) and XX:PermSize to 64mb.
Arnar Gunnarsson
-Xmx is allocated upfront because the JVM requires a block of contiguous address space. But that does not mean all this memory will be used. On a Linux system, it will be marked as inactive and will not be resident. This is why your RSS (Resident Set Size) can be lower.
Vincent Robert
+1  A: 

Java allocates as much virtual memory as it might need up front, however the resident side will be how much you actually use. Note: Many of the libraries and threads have their own over heads and while you don't use direct memory, it doesn't mean none of the underlying system do. e.g. if you use NIO, it will use some direct memory even if you use heap ByteBuffers.

Lastly, 100 MB is worth about £8. It may be that its not worth spending too much time worrying about it.

Peter Lawrey
Peter, I'm running roughly 70 Tomcat instances across many Application servers. This figure really adds up.
Arnar Gunnarsson
So how do you deploy new applications and roll them back/remove them independantly. You are effectively using a root/system owned flat file as a database without the support of transactions or independant operations. IMHO The more services you have the worse your solution sounds to me. If you have multiple boxes, the chances of one system not deploying correctly must be an issue for you.
Peter Lawrey
A: 

Not a direct answer, but, have you also considered hosting multiple sites within the same Tomcat instance? This could save you some memory at the expense of some additional configuration.

Christopher Hunt
A: 

Try using the incremental garbage collector, using the -Xincgc command line option. It's little more aggressive on the whole GC efforts, and has a special happy little anomaly: it actually hands back some of its unused memory to the OS, unlike the default and other GC choices ! This makes the JVM consume a lot less memory, which is especially good if you're running multiple JVM's on one machine. At the expense of some performance - but you might not notice it. The incgc is a little secret it seems, because noone ever brings it up... It's been there for eons (90's even).

Mike
A: 

Arnar, the JVM also mmap's all jar files in use, which will use NIO and will contribute to the RSS. I don't believe those are accounted for in any of your measurements above. Do you by chance have a significant number of large jar files? If so, the pages used for those could be your missing memory.

ahawtho