0

Recently I got a VPS server and I'm running Coldfusion, the website was running fine until it got more and more traffic and I started to encounter 'OutOfMemory' exceptions.

I thought simply to rise the memory of the VPS server, but this didn't help.

After doing some Google searches I found a setting in de CF Admin settings to set the JVM Heap memory. It was on the standard: Max Heap size 512MB and Min Heap size was empty. After playing around a bit I have now set it to Min 50MB and Max 200MB, good things is that I'm not getting the 'OutOfMemory' exceptions anymore. So far so good!

But with about 50 active visitors on the website, the website starts to get slow. The CPU usage is only about 8% (Windows Taskmanager), also the taskmanager show only about 30% of the 3GB RAM in use.

So I'm thinking that my values could be tweaked to use more of the RAM. Honestly I don't understand these JVM Memory heap settings, so I have no clue what is a good setting for me.

I found a CF script that displays the memory usage, the details are:

Heap Memory Usage - Committed    194 MB  
Heap Memory Usage - Initial  50.0 MB
Heap Memory Usage - Max  194 MB
Heap Memory Usage - Used     163 MB
JVM - Free Memory    31.2 MB
JVM - Max Memory     194 MB
JVM - Total Memory   194 MB
JVM - Used Memory    163 MB
Memory Pool - Code Cache - Used  13.0 MB
Memory Pool - PS Eden Space - Used   6.75 MB
Memory Pool - PS Old Gen - Used  155 MB
Memory Pool - PS Perm Gen - Used     64.2 MB
Memory Pool - PS Survivor Space - Used   1.07 MB
Non-Heap Memory Usage - Committed    77.4 MB
Non-Heap Memory Usage - Initial  18.3 MB
Non-Heap Memory Usage - Max  240 MB
Non-Heap Memory Usage - Used     77.2 MB
Free Allocated Memory: 30mb
Total Memory Allocated: 194mb
Max Memory Available to JVM: 194mb
% of Free Allocated Memory: 16%
% of Available Memory Allocated: 100%

My JVM arguments are:

  -server -Dsun.io.useCanonCaches=false -XX:MaxPermSize=192m -XX:+UseParallelGC -     Dcoldfusion.rootDir={application.home}/../ -Dcoldfusion.libPath={application.home}/../lib

Can I give the JVM more memory? If so, what settings should I use?

Thanks very much!!

1
  • Sorry, i know this is a question, but not sure how to contact the original poster otherwise. Could you post the code behind that CFscript which shows all the memory usage? i've never come across one with all of that detail and would love to get it.
    – user203931
    Dec 30, 2013 at 22:56

4 Answers 4

1

A really good reference to read on GC and performance is Oracle's GC Tuning whit

http://www.oracle.com/technetwork/java/gc-tuning-5-138395.html

In general, the more memory you can allocate to your JVM, the better. The larger you set the young generation (to half or so the total VM size) the better. I've played with JVMs of up to 28 GB in size.

For monitoring, you want to use jconsole (if you're a sysadmin, it's horribly interfaced, instrumented, and limiting, but it's what you've got) and watch in particular your GC activity and total sweeps. This will also give you a sense of what your memory utilization patterns look like. This is a GUI monitor instrumented in Java. You'll need to enable the JMX extensions in your JVM to use it.

For seeing what's actually using memory, the 'jmap' utility will show you both heap size ('jmap -heap ') and an inventory ("histogram") of objects in heap ('jmap -F -histo '). The first usually runs quickly, I've seen the second run for 20-30 minutes, during which the JVM is nonresponsive to other tasks, so this isn't something to use lightly on production instances.

Somewhat counterintuitively, the larger you make your ParNew / young generation, the less often, faster, and more effectively, GC runs. GC works by tracking live objects in heap, and runs as ParNew fills up. With a bigger ParNew, more time elapses, and more objects have expired (died), so GC runs less often, and more of the objects have died. allowing more memory to be GCd. We had a configuration in which ParNew was set absurdly small (~50 MB or so), and bumping it to 1-2 GB dropped GC overhead to about 1-5% of what it had been previously (0.01% - 2% of CPU depending on host/workload now, had been 10-50%).

You'll also want to size PermGen such that you don't run out of space. This is where persistent objects (mostly classes) are kept, and when you run out of space it's usually a Bad Thing.

1

The answer of course is "it depends" on your application. The first step would be to monitor your memory usage. There are a lot of products that can help: SeeFusion, Fusion Reactor...plus standard JVM monitoring like jconsole and VisualVM.

Figure out what your current heap usage is and bump it up until the GC becomes more stable. Also make sure your PermGen space is large enough (if you are using a framework or a lot of objects this could be an issue.)

In practice, I've actually ended up lowering the heap size when our apps have not come close to the

0

The system is likely starting to slow down at higher load due to the more frequent garbage collection needed to keep the heap that small.

The max heap size literally limits the maximum amount of memory consumption by the JVM; if you want to let it have more of the system's RAM, you'll want to increase the maximum heap size.

However, if the software is chewing through that much memory and requiring that much garbage collection, then you may only be delaying the inevitable with a larger heap size. Try a higher setting (start with 1024 MB, then go to 2048 MB), but if that only delays the crash, then you'll need to optimize your application code to be gentler in terms of RAM usage.

0

Kai put together this great set of information on JVM tuning. 50min and 200 max is quite low. I;d suggest ( on 32bit ) try 1024 as both the max and the min and see how you go.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .