tirsdag 16. desember 2008

Comparing 64bit and 32bit Linux and Java

I'm running a Tomcat server which needs to allocate large (>1GB) of memory. For that, it would make sense to run Linux and Java in 64bit mode, thus being able to allocate much more than 2GB (Java) or 3.5GB (Linux) of memory. On the other hand, there are a lot of rumours on the net that 64bit Linux uses twice or more the memory. There is a good article including measurements explaining that 64bit java needs approx. 50% more memory for strings and integers.

Here are my results tested on the same machine as virtual xen-hosts, using debian-etch in i386 and amd64 bit mode. The machines got both 256MB memory and no swap:











Action32bit64bit
free after boot219M217M
file-size c-prog10M12M
data-allocationmax 217M217M
free after data-allocation224M224M
java -servermax 208M @ Xmx214Mmax 203M @ Xmx234M
java -clientmax 209M @ Xmx214Mn.a.


Both the C and the java-program simply allocate some memory. The java-program can be seen at the end of this blog. The java-program tried to allocate 256 * 1MB, until it threw a OutOfMemoryError. The Xmx settings have been adapted so high, that Linux didn't kill the JVM with 'Out of Memory'. It was astonishing to see that the Xmx settings could be set higher on the 64bit jvm, while the maximum available memory within
java was slightly lower.

The results are an assurance that 64bit Linux does not require much more memory than the 32bit Linux. At least not for a server machine with only 64bit libraries installed, and applications which don't require many pointer. Desktop machines may require much more if also the 32bit libraries need to run due to some 32bit only programs. The biggest difference is code size (20%). But gcc is known to have different default options in 32bit and in 64bit mode.

Example of code run to test data allocation:

public class Main {
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("Main: buffers size (in m)");
System.exit(1);
}
int buffers = Integer.parseInt(args[0]);
int size = Integer.parseInt(args[1]) * 1024 * 1024 / 4;
java.util.Vector store = new java.util.Vector(size);
for (int i = 0; i < buffers; i++) {
store.add(i, new int[size]);
System.err.println("allocated buffer " + i);
}
}
}