Reducing the memory consumption of your Java application (Part III)
This is kind of a reply to this The First Law of Optimization entry by Valery,Silaev, who obviously likes to read my blog. I also would like to explain im more detail, why I think knowing the String api is pretty important.
“Empty String in JVM occupies 40 bytes in memory? Wow, that’s cool to know!”
Sure this is important to know. My experience is that a lot of developers, do not know what the overhead of String is. This is not just a feeling, but it’s supported by a lot of data taken from heap dumps and of course by speaking to the developers.
This has nothing to do with premature optimization, which as we all know, who read Knut every evening as a bedtime stories for our childs “is the root of all evil (or at least most of it) in programming.”
It’s about getting the basic things right, and fact is that the class String tends to be overused and pretty often is used incorrectly .
“The Expensive Compiler Story”
Of course I’m aware, that there are certain situations, in which the compiler optimizes away the overhead of “+”, and I was simplifying because I didn’t want to create a big blog entry with 154 lines.
But honestly, if you tell the developer to use StringBuffer on JDK 1.4 and StringBuilder on JDK 1.5, and the developer has to maintain code for both JDK. What do you think most developers will do ? I guess they will just go ahead with StringBuffer, at least in code that is unlikely to be performance critical. As a matter of fact, on an recent JVM, uncontented synchronization is almost always practically zero.
Telling a developer,”just test everything by yourself”, isn’t really practical nor efficient, because it’s just duplicated work. Of course you want to profile/measure your complete application, to be sure that you don’t have any unexpected bottlenecks.
It Is String.intern() good or evil ?, String.intern() should rather not be used, at least on SUN VM’s up to JDK 1.5. But maybe a JVM of a large software company in Walldorf, will improve the situation within the near future 😉 By the way using “StringA == StringB” rather than “StringA.equals(StringB)” will usually not make a difference, because the first statement in String.equals does “StringA == StringB” anyway.
Yes reflection performance improved a lot on most VM’s. I’m not sure whether it’s fast on all VM’s. One problem with reflection at least on SUN VM’s is that classes are generated on the fly, which occupy permspace. Ever wondered about messages like this in your std_server0.out ?
[Unloading class sun.reflect.GeneratedSerializationConstructorAccessor51] [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor143] [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor93] [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor211] [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor207] [Unloading class sun.reflect.GeneratedSerializationConstructorAccessor47]
These messages are caused by the unloading (due to a Full GC), of the automatically generated classes for reflection. As far as I remember there was a problem with a non SUN VM, where this would cause very long GC pauses (minutes), because the VM was not optimized for this kind of stuff. And also reflection got pretty fast in the meantime, it can still be infinitely slower than a simple call, because it defeats inlining.
“Do not optimize object construction”
I do not fully agree with this statement. If this means don’t care about how much objects you created, then I disagree. Sure object creation in Java is freaking fast, almost always faster than a malloc in C and the clean up through the minor GC is very efficient. But the problem is that you must be carefull about how long your objects live, because if they live to long they will go to old space and can only be reclaimed by a full GC, which is costly.
Predicting how long an object lives can be very difficult in an complex J2EE enviroment. It also doesn’t make much sense to create lot’s of duplicates of objects which are really constants. More about this in later blog. For more information about Garbage Collection in Java (1.4) check this link
@Valery,Silaev. I like to read your blog too 🙂 In fact I agree in principle with most of your statements.