I've been running 64-bit Java on my 64-bit Linux box for a week,
and it's interesting. Ant and SmartFrog are happy, but the IDEs
-the big memory consumers- are troubled. Intellij IDEA, both 6.0.5
and 7.0M2 have real performance problems, especially in interactive
dialogs. Eclipse and SmartSVN both need lots of memory. Even jEdit
gets very choppy during GC, a GC which kicks in more often with the
standard defaults.
The key thing is that tests show that 64-bit
JVMs consume 40-50% more memory than programs run under a 32 bit
JVM.
That means
- Your 4GB Java process now needs 6GB of RAM to hold the same
amount of data,
- all programs with tuned -Xmx , -XX:PermGen or thread stack size
settings for 32 bit processes are now broken
- The probability of a cache miss has (at a guess) just increased
by 40-50%. Every program that ships with a set of JVM settings is
broken, though those that run with the defaults appear to pick up
some expanded defaults and cope better.
- The GC routines now have an extra 40-50% more memory to move
around.
There are also other consequences, like more memory to zero when
creating an object, startup times will probably be worse, etc,
etc.
(1) is the fact, we can't deal with that directly, though
there's some interesting research there.
(2) is an inconvenience, which is something I can only fix
in Ant. It would make sense, surely, for a 64-bit JVM to
automatically multiply all -Xmx options by 1.5; we could always
have a secret -XX:64multiplier option for 64-bit only use.
(3) is a major performance issue. If the P(cache-miss)
increases, then apps that are data intensive are going to be
slower, and that extra GC load is going to make things less
reponsive -which is presumably why it's the IDE's that are showing
the problems. I don't notice the performance hit in the command
line tools as the slowdowns are hidden by the overall machine
speedup.
This is a serious and fundamental problem with 64-bit Java. Is
it intractable? Well yes, if you stick to full 64-bit pointers
throughout your objects. But there are alternatives, such as Space-Efficient
64-bit Java Objects through Selective Typed Virtual Addressing
and
Object-Relative Addressing: Compressed Pointers in 64-Bit Java
Virtual Machines
The latter is quite interesting; you use 32 bit wide, 4-byte
aligned pointers, with bit 0 being a flag to indicate direct (0) or
indirect (1) handle reference. For indirect refs, you go via a
lookup table. The hope is that most references are within the local
4GB space, and if not, well, you can indirect. The memory savings
and improvements in $L1-$L3 cache misses should compensate for the
extra work on the long-haul references. It's a bit like the old
Win16 short and long pointer design, except in Win16 you used to
have to decide in advance how long a pointer would be, your pointer
arithmetic was doomed, and you couldn't reliably do pointer
equality tests in your C/C++ code. And handles had to be handled
explicitly, with -in windows 2.x- you needing to lock down every
handle before use, and the developers maintaining a list in their
head of which Win16 API calls would cause the "OS" to switch to
another thread and so move pointers. ::SendMessage(), ::DialogBox
and the like would be enough to cause another program loaded in the
single memory space to run, and your pointers to be moved
afterwards. Windows 2.x dev was a long time ago in my life, and I
don't miss it, not at all.
Because Java doesn't make pointers explicit, all those equality
tests are left as a problem for the runtime, not user code, and
with the switch from pointers to handles being handled magically
-both take up the same amount of space in the allocated structs.
The problems are still there though, with 0 no longer matching
NULL, for example.
One of the nice things about this design is that small-memory
apps, those using <4GB of heap, don't need any indirect handles
at all. They should have nearly the same memory needs as the 32 bit
apps. So programs like eclipse (only 800MB footprint) and IDEA
(1.3GB) will run happily without needing the extra memory a 64-bit
JVM offers -but if they do need it, it will switch in
seamlessly.
This is all still research; doesn't address my immediate
problems with the IDEs. The only solution there is to install a
32-bit JDK alongside the 64-bit one, and try and get the IDE's to
work with that. There is a 32-bit JRE for Ubuntu-AMD64
(ia32-sun-java6-bin), but I haven't tracked down the full JDK set
up to install into the 64-bit OS, which is what the IDEs need.