views:

1395

answers:

15
+10  Q: 

Speeding Up Java

This is really two questions, but they are so similar, and to keep it simple, I figured I'd just roll them together:

  • Firstly: Given an established Java project, what are some decent ways to speed it up beyond just plain in-code optimization?

  • Secondly: When writing a program from scratch in Java, what are some good ways to greatly improve performance?

Please stay away from general optimization techniques unless they are Java specific.

I asked this about Python and Perl earlier. For Java I'm wondering what good tips/tricks are out there to improve performance and if there are any particularly good Java profilers.

+2  A: 

For profiling, try JAMON for time monitoring, and the NetBeans profiler for general performance and memory monitoring.

Nerdfest
+5  A: 

Using StringBuilder in place of large sets of String concatenation gives a great relative performance boost.

However, I can't avoid saying the general practice performance gaining benefit, Profiling. I don't know Java profiling off-hand (Only used the language academically), but profiling helps you identify problem sections of your code, and it is a lot easier to fix specific sections since you have something to look up.

Guvante
In many cases, the VM will turn string concatenation into StringBuffer manipulation. I'd be be surprised if doing this manually gave any performance boost except in the most bone-headed of cases.
skaffman
@skaffman, Don't confuse StringBuilder (unsynchronized) with StringBuffer (synchronized.)
finnw
Since Java 5, the compiler turns String concatenation into the equivalent StringBuilder calls. If you write a trivial class with String concatenation in it, compile, and then open up the .class file in a text editor, you'll see the StringBuilder replacement calls.
shadit
Neither the compiler nor the VM will replace string concatenation with StringBuffer when it happens inside a loop (i.e. a String scoped outside the loop is concatenated to inside the loop) - which is pretty much the only time where it really counts.
Michael Borgwardt
+2  A: 

The same as for any language, use appropriate algorithms and data structures.

One good thing of OOP, is that you might be able to change implementations of an object without changing the interface. That lets you start coding with naïve implementations and replace them if needed.

Javier
+14  A: 

Firstly : by code optimization, I would assume that you've done the right algorithms and right implementation of algorithms. In which case, you would use the profiler and look at how often your garbage collector(GC) is collecting garbage and how much time it is using for doing that. Then you start working on the GC options -- but beware you can get into trouble if you don't know what you're doing.
I assume that you're using java 5/6. In which case, I'd go through the java 5 tuning guide at http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html. There is also a very very good newletter on java performance called http://www.javaperformancetuning.com/ to which you can subscribe.

Other than that, look at how many try/catch blocks you can eliminate. See if you can eliminate unnecessary throwing of Exceptions.

Use Caches where you can BUT don't over do it.

Read Effective Java, 1st and/or 2nd Edition

Profilers : I use yourkit. It's pretty good for java 1.5 and above. You can get a personal license. Other profilers are also good as well.

Just like you have unit and integration tests, it does NOt hurt to have some performance tests that you run as part of your CONTINUOUS INTEGRATION(CI) builds. This way you know when you regressed, especially if you are using a good CI build server.

anjanb
try / catch is fairly cheap these days. I wouldn't worry about that.
Alex Miller
Note 'Caches' should not include object pools, which are not recommended these days except in the case of "expensive" objects like thread pools or database pools.
sk
+8  A: 

Use the latest VM--they are getting better all the time.

Profile and test. Never optimize your code unless you are absolutely sure you need to.

If it's a GUI app, Switch from Swing to AWT or maybe Eclipse's toolkit, it's supposed to be pretty quick. This is more important on older VMs (I've been working embedded for a while and we are actually in a 1.0.x vm, swing isn't even available)

I know this isn't specific to Java exactly, but not allocating objects--this includes string concatenation in a loop (outside a loop it's pretty acceptable. This is the biggest thing you can probably do.

You can also keep objects around instead of freeing/reallocating them. There are some "reference" classes that can be used to hold onto objects that you don't need but might want to reuse--the GC won't delete them unless it needs the space.

Allocate more space if needed with the -MX argument.

It's kind of hard to speed Java up much--HotSpot already does so much for you that anything you do that you think might speed up your code can often slow it down.

Bill K
Rendering in Swing is not that slow. Most of the time it's the business code that blocks the EDT.
Roland Schneider
Good point, but I did actually have a 1.1 embedded project (Signal analyzer for Agilent) where the GUI was in AWT, we re-coded it in swing, then found that swing was significantly slower and we re-coded it in AWT. This is a case where we were actually drawing the trace for the signal analyzer and needed at least 20 fps.
Bill K
+12  A: 

Make sure your log level's aren't accidentally left at DEBUG :)

matt b
Accidentally. Yeah, right! :-)
agnul
It is amazing how big a difference this can do.
Christian Vest Hansen
+11  A: 

"Measure, don't guess."
Here is a good article on using the NetBeans Profiler to speed up the iText PDF library. I've used the NetBeans Profiler myself, and I've found it to be very easy and useful in tracking down some performance issues I was having.

For an older application, simply moving to Java 6 might be a performance boost. See this whitepaper for information on the performance improvements in Java 6.

Michael Myers
+1  A: 

I've seen that sometimes just giving the JVM more heap memory will help a sluggish application. This is controlled with the -xmx and -xms JVM options at startup.

Vinnie
Happens because you are close to exhausting the heap space and thus have more garbage collections to attempt a clean-up. You can either increase heap space as you suggested or find the culprit that is taking up all the memory.
jlouis
+3  A: 

Another potential performance gain can be realized by switching to a faster VM. They are not all made equal, and some are better suited to different types of applications. They may also each have specific types of customizations that they support, as well as the standard ones.

Some comparisons

Also, be wary of doing microbenchmarks for testing performance, as they are not meaningful due to the way most VM's work. So some very simple performance tests may behave differently due to reasons that are not obvious.

Simply running a test and then changing a small bit of code or a VM option and running it again, may produce different results, but have nothing to do with the changes you made.

Robin
A: 

There's one thing you should do right from the start of a project that will be an enormous help: write readable code.

Don't try to write long methods to avoid method calls. Compilers will inline if necessary, but may produce poor code for long methods. If the code is difficult to read, often performance problems will be caused by it doing something mental that you can't see for the clutter.

Tom Hawtin - tackline
+1  A: 

Java 1.6_07+ comes with its own profiler. It is called Java VisualVM. Just type jvisualvm on the command prompt if you have your %JAVA_HOME%/bin on your PATH.

Joshua
All JVMs since at least 1.2 have come with in-built profiler (-Xrunprof:cpu=samples or such on command line). Visualization part may be new.
StaxMan
A: 

Here is an (older) document by Peter Sestoft which is worth reading: Performance in java. Some of the advice is probably not true anymore since Java got a lot better with the later versions in optimizations. But there are still a good set of gems in there to utilize and try when the profiler has found something you can't do any other way (ie, change algorithmically).

jlouis
+2  A: 

Don't optimize blindly. Use Yourkit or any other good profiler to find out the "hotspots" in your application.

You need not only take a look a CPU time, but also at how much memory is allocated and freed for certain step. You also want to ensure that you don't have memory leaks, or high memory consumption. The best tool to analyze memory consumption that I know is the Eclipse Memory Analyzer (http://www.eclipse.org/mat).

Other dimensions are thread contention and IO problems. For a simple way to analyze contention problems, check my old blog at https://www.sdn.sap.com/irj/sdn/weblogs?blog=/pub/wlg/4737

kohlerm
+2  A: 

You also asked this in regard to C#, and I would give the same answer, and that it's a mistake to start off being language-specific. Once you've squeezed every cycle that you can get using general techniques and approaches, then language-specific stuff might make a difference.

Mike Dunlavey
A: 

It may seem irrelevant, but there is a list of speed tips on the Android developer site. It's running on a phone on non-standard dalvik bytecode but many of the tips listed there are universally applicable to Java in general.

izb