64 bit JVM:s may come with severe penalties on memory constrained systems

I’ve been toying around with Spotifun – a Grails based webapp  – on a Rackspace cloud virtual machine.

The entry level rackspace offering is an instance with just 256 MB memory. I quickly discovered that 256 of RAM doesn’t cut it for running Tomcat with a single Grails app with a few grails plugins (~50MB WAR file size). The WAR barely deployed before the JVM ran OutOfMemory.

Decided to migrate my instance to a Rackspace plan with 512 MB of RAM.  This offered a sort-of reasonable experience. But just sort-of,  frequently episodes which excessive 10+ second response times would occur. Heavy garbage collection and/or swapping activity appeared to be a likely culprit, but as I was to cheap to just upgrade to a plan with even more memory I decided to whip out JConsole and have a look on the running JVM via JMX. I discovered that the JVM on the Rackspace instance was far more memory hungry than the JVM on my development work station.  Almost twice the amount of heap memory was used (measured post Tomcat startup)! And this on a system constrained to 512 MB (of which mysql and the base Ubuntu OS will obviously claim a significant share). Further investigation led me to the reason:

# uname -a
Linux 2.6.24-23-xen #1 SMP Mon Jan 26 03:09:12 UTC 2009 x86_64 GNU/Linux

Rackspace is obviously running on x64 hardware, causing Ubuntu apt-get to install a 64-bit JVM when java is installed. 64-bit software generally occupy more memory than their 32-bit counterparts, see the Wikipedia article on the subject for further details. The remedy is in this case however only a:

apt-get install ia32-sun-java6-bin

…away. A quick change to JAVA_HOME in Tomcat’s startup script to ensure that the correct JVM is used and memory consumption was back to sane levels. After reverting to a 32 bit JVM I’ve yet to see abnormal response times from Spotifun.