Showing posts with label performance. Show all posts
Showing posts with label performance. Show all posts

Sunday, 26 February 2012

Compatible Images

A couple of weeks ago I was tasked with improving the performance on a legacy java swing application that was really crawling.  It would repaint the whole screen on any event, which it could receive a lot of, and painting the whole screen was really slow.  By using compatible images instead of the default kind of image read by ImageIO, the painting code was sped up by a factor of 70 and the event frequency was a non-issue.  The whole change was about 10 lines of code, much less than that to make the software use the graphics clip.

If you are having an issue with graphics performance make sure you try compatible images before trying anything else since it is so easy to introduce.

Before deploying to site I was worried that the speed up I was seeing was in some way down to my dev machine working well with compatible images so I wrote the tool below to test if the improvement was the same which it was.  Some notes:
  1. The tool requires an image.  When I attempted to create an in-memory image there was no difference in run times.
  2. Results are printed on the command line so remember to use java.exe and not javaw.exe
  3. I went to some effort so that this program was a single class to make it easy for the support guys to run.  I don't usually like to implement Runnable on a class that isn't just a Runnable.

Wednesday, 3 August 2011

Using Method Handles

A few weeks ago I ran some tests pitting method handles against typical reflection to see what was faster. The result was that reflection was faster although since it was a quick test I don't have the result data or what run configuration I used. Now that I'm tasked with looking into porting our core systems to Java 7 I thought I'd take a more critical look.

Below is the source code I used to run the test. It calls a method on a class called Incrementer a million times. I didn't notice any difference when running the methods several times when running the test several times before timing values to "warm up" server mode.


Note that this code throws an exception when run from eclipse. I had to use the javac/java executables from the command line for this to work. When running the class in mixed mode I got the following results:

java -verbose:gc MethodHandleTest
[GC 4416K->141K(15872K), 0.0011714 secs]
[GC 4557K->141K(15872K), 0.0006216 secs]
[GC 4557K->141K(15872K), 0.0006387 secs]
reflection took 515ms, result is 1000000
method handles took 16ms, result is 1000000

There is plenty of garbage collection happening but not enough to account for the huge time difference. When running in server mode I got the following results:

java -verbose:gc -server MethodHandleTest
reflection took 47ms, result is 1000000
method handles took 15ms, result is 1000000

java -verbose:gc -server MethodHandleTest
reflection took 32ms, result is 1000000
method handles took 31ms, result is 1000000

All runs of the test gave almost identical results to the above where method handles would be twice as fast as reflection or equal with no garbage collection. Interestingly, if I comment out the increment of the long value the same result as with the increment is produced:

java -verbose:gc MethodHandleTest
[GC 4416K->141K(15872K), 0.0011488 secs]
[GC 4557K->141K(15872K), 0.0006595 secs]
[GC 4557K->141K(15872K), 0.0006482 secs]
reflection took 500ms, result is 0
method handles took 31ms, result is 0

This makes me think that incrementing the long is a very small proportion of the time it takes for the reflection example to run and the majority is for calling the method through reflection. In server mode the reflection call is JITted and almost identical results are produced. This is mostly conjecture since it is quite difficult to work out what the Hotspot compiler is doing.

In conclusion, method handles consistently performs as good as, or better than reflection no matter what run configuration you are using. Stability is an issue with the current tools, eclipse will have to support Java 7 before I could use method handles in our systems.

Saturday, 18 December 2010

String and CharSequence Concepts

Java String performance has been bothering me for a while.  The String class is needlessly overencumbered with fields supporting features that are only needed in a few cases.  For example the count and offset fields provide a range feature so that a string can use an existing char array without copying the required part into a new, smaller array.  This is a useful saving when used but I would imagine that features that use it like subsequence are the exception.

I believe the problem is that the class hierarchy is fundamentally incorrect.  There are two primary classes based around strings: String (concrete) and CharSequence (an interface).  The concept is wrong, string is the concept and char sequence is an implementation of a string.  The collections framework seems to agree, with the List, ArrayList (or other implementation) and SubList classes.

A small saving of two int fields maybe, but a lot of freedom to create custom string implementations.

Update 03/08/2011
I realised why all APIs require a String and not a CharSequence. Because the String class is immutable the char is guaranteed not to be changed mid way through an operation, and bugs that would wrongly be attributed to the API.