[H-GEN] Which is better?

Adrian Sutton adrian at intencha.com
Tue Apr 27 09:13:21 EDT 2004


> Re: "This is flat out wrong; and a good example of the sort of dodgy
> practices associated with premature optimisation."  Well, as I hope I
> have shown, its not flat out wrong.  In fact its merely repeating the
> advice given by Java's designers.  For example, they say instead of
> writing:
>
>   String timeFormat(DateTime t) {
>     SimpleDateFormat myDateformat = new SimpleDateFormat("...");
>     return myDateformat.format(t);
>   }
>
> write:
>
>   static SimpleDateFormat myDateformat = new SimpleDateFormat("...");
>   String timeFormat(DateTime t) {
>     return myDateformat.format(t);
>   }
>
> You see lots of "howto" examples like this.  In Java, not writing your
> code like this could almost be considered a bug.  Its not like it is
> harder to read.

They suggest you do that because SimpleDateFormat is an expensive 
object to create due to the amount of string parsing it does (the ... 
in your code).  You will find that the memory allocation is an 
insignificant portion of the time taken and profiling will show this 
quite easily.  You've fallen into the premature optimization trap 
again, it will be faster with the second example but not for the reason 
you think, and then *only* if that method is called more than once and 
is on the critical path.

Memory allocation in Java is not expensive, the recommendations for 
Java memory management is *not* to pool objects to avoid memory 
allocation as it usually winds up slower then if you just created many 
objects.  The reason for this is that Java uses a generational garbage 
collector so the cost of creating objects is very low and the cost of 
collecting short lived objects is also low, however once an object 
moves out of the young generation the costs to garbage collect it are 
significantly higher, thus holding an object for longer than required 
will generally slow down the program due to the extra work the garbage 
collector has to do.  This obviously doesn't apply to objects which 
require significant processing in their constructor - such as 
SimpleDateFormat and database connections.

In the past 5 years of programming in Java there has only been one 
occasion where excessive memory allocation was a significant 
contributor to the slowness of the application.  In that case it was in 
the border painter for a HTML layout engine - there were some 1000 
instances of the border painter that had been created and each time a 
repaint was done any of those borders which may need to repaint would 
process each of the four sides of it's borders and create a BorderData 
object for that side.  So all up there were as many as 4000 BorderData 
instances being created each time the user moved the mouse over the 
component.  Even then the delay was not memory allocation but the fact 
that so many objects had been created that many of them spilled out of 
the young generation into the older generation and a full garbage 
collection cycle had to run to clean them up.  Obviously running a full 
garbage collection cycle whenever the mouse moves seriously affects 
performance.  I replaced the BorderData instances with class variables 
in BorderPainter that stored the values that were in BorderData 
temporarily.  While there were still massive numbers of objects being 
created and destroyed constantly, they all stayed in the young 
generation and were cleaned up without any noticeable on program 
performance.

If you haven't profiled it, you don't know what you're talking about.

> To put it another way, if someone is going to optimise your program,
> they are unlikely to every change the first version into the second -
> ever.   Since the second version is harder to read don't do it.  But, 
> if
> they see the SimpleDateFormat example I gave earlier in a slow running
> program, they will probably curse him.  They will wonder where else he
> has done something like this.  Its something every good Java programmer
> keeps in the back of his mind - is this memory allocation necessary?
> Can I move it outside of the loop?  Outside of the function?  Outside 
> of
> the class?  If it doesn't seriously hurt the code readability then the
> answer is almost always yes - he should.  Like any rule it can be
> overdone, but applying it well will generally save time.

This is absolutely false.  Any good programmer in any language should 
be thinking - does this code solve the problem I'm presented with?  Is 
this code maintainable?  Bad programmers think about optimization, good 
programmers make it right then profile it, then make it fast.  Anyone 
who tries to do things in a different order is at best wasting their 
time.

The only thing a good Java programmer keeps in his head that 
programmers in other languages generally don't is: "is this platform 
specific?"  You will find more Java performance problems caused by 
platform specific assumptions than you will memory allocation.

Regards,

Adrian Sutton.
----------------------------------------------
Intencha "tomorrow's technology today"
Ph: 38478913 0422236329
Suite 8/29 Oatland Crescent
Holland Park West 4121
Australia QLD
www.intencha.com





More information about the General mailing list