Eye on Java performance Improvements
An anonymous reader writes "Performance. It's the one aspect of the Java platform that continually takes abuse. But the overwhelming success of the platform on other fronts makes performance issues worth serious investigation. In this article, Intrepid optimizers Jack Shirazi and Kirk Pepperdine, Director and CTO of JavaPerformanceTuning.com, look at compilation speed, exceptions, and heap size tuning."
They talk about how expensive it is to create an exception, and caution against it. Beware undue aversion to exceptions! For example, java.io.File.getLastModified(), if called on a file that doesn't exist, will return 0. An exception really ought to be thrown, but who's going to change the API now?
People emphasize performance too much. Look how successful PHP has been despite its slowness. Deal with functionality first, and only worry about performance if and when it's a problem.
I always get amused when open source people spout of about how slow Java supposedly is and how much they love perl/python/php in the other. Java is pretty much faster than all of those. Yet nobody ever dogs on python (say) for being slow. Why?
Actually, if you read the article carefully, you find that it says that you should only create exceptions in exceptional cases; that's the slow step, throwing and catching are fairly fast.
So, presumably, if you create a single exception, and keep throwing and catching it, the performance would be much better. Of course the stack data will be wrong, since it will represent the place where it was created, but for many applications that may not matter.
-WolfWithoutAClause
"Gravity is only a theory, not a fact!"...or C. If you want to hack something together, use Perl. If you want lots of reusable code/objects/classes/whatever use java. If you want whatever your working on to be stable, tight and fast then use C for a small project like this...
I used to stress about Java performance. I'm not sure it was ever warranted. Certainly, things are plenty fast enough now.
Not only have the JVMs improved - e.g. hotspot - but the servers and PCs I'm using now are 3 times faster (2.4Ghz vs. 800Mhz a few years back).
What I think they need to concentrate on now, is getting the memory usage back down. 100MB to run an eclipse IDE is just too fat. And it's hard being a JSP Host when each Servlet engine chews up 60MB of memory on my host servers.
FWIW, the 1.5 release sounds like memory will get a good looking at. Let's hope so.
...with less attitude (sorry, somehow I'm picking up the popular slashdot i-know-more-than-god tone... gotta watch that).
...and you may have also heard that this is nonsense and a great way to *ensure* that your project will fail because it's unuseable.
The article in question does do a good job of explaining why Exception creation is expensive.
I'm still dead-set against reuse of Exception objects, though, for some pretty good reasons. I've seen the suggestion before, and it bothers me because as optimizations go, it's very short-sighted.
I'm sure you've heard the suggestion to "code for the human, not for the machine", because you code *will* need to be maintained, unless your project fails.
As usual, the best answer is somewhere in-between. Every programmer should have the human reader in mind while designing and coding, but they should *also* design for efficiency. It has to be an informed compromise.
Reusing Exceptions is one of those examples that I like to use of how *not* to optimize. It's a basic misuse of an integral part of the Java idiom. Everyone understands how Exceptions work, and how to use the stacktraces to find your error. It's dependable. The poor sucker who's on call when a customer calls because this application keeps crashing takes stacktraces for granted, and is going to be beating his head on his desk after 2 hours trying to figure out what is going on.
This is a big cost. Okay, sometimes a cost is worth it, in optimizations. If this is a core data-crunching library that absolutely must perform at peak efficiency, maybe this is worth the painful maintenance cost.
In this case, though, I can't think of any benefit to balance this cost, except that a programmer somewhere is pleased with herself for using an optimization she read in a book. If this data-crunching library is throwing Exceptions left and right in its normal processing, it's using Exceptions wrong.
I hadn't thought about using the pre-made Exception hack to escape recursion -- it seems like a quicker way to get out than unwinding the recursion, after all -- but thinking about that more, I wouldn't suggest it even then. NOTE: comments below are not performance-tested, so if you really want to use recursion in a performance-critical part of an application, you should run some tests first.
To begin with, recursion isn't a very efficient process in Java. Each time the method calls itself, all of the current local variables are stored, a new copy of the method is made (with new locals), and execution continues in the new copy.
When you unwind the recursion, each of those stack frames and associated variables will need to be removed from the stack/heap and cleaned up, whether you exit normally or via an Exception.
If you do exit via a reused Exception, you're misusing the functionality (as discussed above), and the benefits -- which will be slim, if any -- aren't worth it, because there are better options.
If you're writing performance-critical code, you should use iteration, all in one method, instead of recursion, because it will perform better than even recursion with an Exception escape (probably in this case the cost is some readability.. recursion can be much more elegant).
If it *isn't* performance-critical code, then you shouldn't be worried about unwinding the recursion. And I still don't like misusing basic Java concepts, but you could even throw a new Exception to escape w/o worrying about performance -- after all, 1 million new Exceptions in 10 seconds is still pretty darn fast when you're only talking about throwing one.
-----
Wow, I hope someone reads this... it was a lot of work to write out!
There are only 10 types of people: those who understand decimal, those who don't, and, uh, 8 other types I forget.
I'm not totally surprised, but I am a little. Hotspot can often do range checking at compile time and remove the run time checks. However, for it to do that successfully may depend on subtle features of the code, so it won't always succeed. Additionally it may well depend on which version of the jre you are working with.
Range checking at compile time is probably best done by the javac compiler. Hotspot is busy compiling and converting java bytecodes at runtime, so it's unlikely it can do the complicated flow analysis required to determine if the runtime range check can be removed. You start from the position that the range check can't be removed, and find a reason to do so... not the other way around.
You're right about version dependency on the JRE for performance. Shirazi's book (linked in my original post) brings this out in great detail. More importantly you have to remove the effect of the hotspot compilation: either tune on the interpreted code only, or let the program run long enough for the hotspots to be found and compiled before looking at performance data. When the hotspot compiled code kicks in all of the statistics gathered up to that point get badly skewed.
Ian.
A physicist is an atom's way of thinking about atoms