views:

440

answers:

5

I'm playing around with writing some simple Spring-based web apps and deploying them to Tomcat. Almost immediately, I run into the need to customize the Tomcat's JVM settings with -XX:MaxPermSize (and -Xmx and -Xms); without this, the server easily runs out of PermGen space.

Why is this such an issue for Java VMs compared to other garbage collected languages? Comparing counts of "tune X memory usage" for X in Java, Ruby, Perl and Python, shows that Java has easily an order of magnitude more hits in Google than the other languages combined.

I'd also be interested in references to technical papers/blog-posts/etc explaining design choices behind JVM GC implementations, across different JVMs or compared to other interpreted language VMs (e.g. comparing Sun or IBM JVM to Parrot). Are there technical reasons why JVM users still have to deal with non-auto-tuning heap/permgen sizes?

A: 

This is because Tomcat is running in the Java Virtual Machine, while other languages are either compiled or interpreted and run against your actual machine. When you set -Xmx and -Xms you are saying that you want to JVM to run like a computer with am amount of ram somewhere in the set range.

I think the reason so many people run in to this is that the default values are relatively low and people end up hitting the default ceiling pretty quickly (instead of waiting until you run out of actual ram as you would with other languages).

aubreyrhodes
Plenty of other languages run on a VM. There's no reason that the VM abstraction has to include a fixed amount of memory.
hobbs
So why does the JVM have (need?) a ceiling at all? Why can't it be flexible enough to request more memory from the OS when the need arises?
mobrule
Consider a JVM as a formal VM. It needs a ceiling because you might be managing multiple JVMs on a machine, just as you do regular VMs. the JVM /will/ reduce it's total heap. The issue really is that JVMs are still hard to dynamically ergonomate (my new word).
Xepoch
+3  A: 

Java gives you a bit more control about memory -- strike one for people wanting to apply that control there, vs Ruby, Perl, and Python, which give you less control on that. Java's typical implementation is also very memory hungry (because it has a more advanced garbage collection approach) wrt the typical implementations of the dynamic languages... but if you look at JRuby or Jython you'll find it's not a language issue (when these different languages use the same underlying VM, memory issues are pretty much equalized). I don't know of a widespread "Perl on JVM" implementation, but if there's one I'm willing to bet it wouldn't be measurably different in terms of footprint from JRuby or Jython!

Alex Martelli
+1 for the data points of JRuby and Jython, which indicate it's not a language thing, but an implementation thing.
Edmund
Fair enough; it still seems, though, that it should be possible to add control without forcing everyone to deal with figuring out their max/initial heap size, max perm gen, ... do you have any references to good technical papers?
Emil
A: 

Python/Perl/Ruby allocate their memory with malloc() or an optimization thereof. The limit to the heap space is determined by the operating system rather than the VM, so there's no need for options like -Xmxn. Also, the garbage collection is simpler, based mostly on reference counting. So there's a lot less to fine-tune.

Furthermore, dynamic languages tend to be implemented with bytecode interpreters rather than JIT compilers, so they aren't used for performance-critical code anyway.

dan04
So why can't the limit to heap space to the VM also be determined by the operating system? Why does it have to be fixed at the time the JVM is started? I'm sure this helps the JVM make a few optimizations to its memory model, but that's not what's driving the difference in performance between Java and Python/Perl/Ruby.
mobrule
+4  A: 

The title of your question is misleading (not on purpose, I know): PermSize issues (and there are a lot of them, I was one of the first one to diagnose a Tomcat/Sun PermGen issue years ago, when there wasn't any knowledge on the issue yet) are not a Java specifity but a Sun VM specifity.

If you use a VM that doesn't use permanent generation (like, say, an IBM VM if I'm not mistaken) you cannot have permgen issues.

So it's is not a "Java" problem, but a Sun VM implementation problem.

Webinator
That's interesting, thanks. Leads to some interesting reading (e.g. http://stackoverflow.com/questions/1009042/what-free-jvm-implementation-has-the-best-permgen-handling); I am doing re-deploys via Hudson periodically which apparently eats up this PermGen space.
Emil
A: 

The essence of @WizardOfOdds and @Alex-Martelli's answers appear to be correct: Java has an advanced set of GC options, and sometimes you need to tune them. However, I'm still not entirely clear on why you might design a JVM with or without a permanent generation. I have found a bunch of useful links about garbage collection in Java, though not necessarily in comparison to other languages with GC. Briefly:

Happy to update this answer with more details if anyone has them.

Emil