[H-GEN] Which is better?

Andrae Muys andrae at internode.on.net
Wed Apr 28 09:02:01 EDT 2004


Russell Stuart wrote:

> For example, it probably isn't worth the effort to pause
> for a few seconds, and check if a statement like "i = j;" can be moved
> out of the loop, but it is worth you while to consider moving "i = new
> I();" out of a loop.

In every example so far I would be pulling up any junior programmer who 
failed to pull the calculation out of the loop.  However my reasoning 
wouldn't have *anything* to do with performance.  The key issue is 
readability!  I ask anyone still following this thread to consider: what 
is the implication in performing *any* operation inside a loop?  Surely 
that it is dependant on the iteration of the loop?  In which case 
putting any invariant calculation inside the loop is lying to the 
reader, and is only likely to confuse.

My number one rule when it comes to code is

"Help the reader reason about the code".

So if you see me write

while (condition(state)) {
   variable = calculateValue(state);
   useVariable(variable);
}

You can be sure that there are at least some iterations where 
calculateValue() will return a different value; simply because if it 
couldn't, I would have expressed it's intent to be invariant as

variable = calculateValue(state);
while (condition(state)) {
   useVariable(variable);
}

(Of course I avoid the global state implied by both the above examples 
like the plague, but I didn't want to stray too far from the examples 
used thus far.)

>  Or perhaps consider making the class "I" immutable
> so you don't have to make defensive copies.

Now this is a *very* important point.  Immutability is a seriously 
underused concept.  One of the watershed days in my coding career was 
when I realised that mutable state is always optional, and that there 
are a number of advantages to foregoing it.  Of course again, the 
primary advantage is in supporting readability; to this performance once 
again plays second fiddle --- then again in this I'm only agreeing with 
your 'defensive copy' comment.

> Both you and Andrae then disagreed with that statement, aggressively.  I
> am still not sure why.  

Because it is premature-optimisation; knuth's quip[0] has lost none of 
it's applicability.  Java is intended to be an object-oriented language. 
  So it is optimised for 1000's of little encapsulated state-machines 
sending 10,000's of messages to each other[2].  The language has 
sufficient flexibility to do structured-programming; it can do 
functional-programming (although lack of LCO[1] hurts here); it can do 
dataflow if you are a real masochist.  However all the above suffer from 
the fact that the language fights against it.  Of course those of you so 
focused on trying to second-guess the implementors for a few extra 
uSeconds of performance have a worse fate.  The runtime is optimised to 
support 1000's of LESM's, and except for a few special cases (which you 
will discover in profiling) you will actually get better performance 
writing OO code without regard for micro-optimisations.

Of course this is dispite the fact that most of your performance will be 
obtained through watching the expected complexity bounds of your 
algorithms, and within those bounds keeping an eye on your IO.

> For the record, I originally said that Harry's
> original optimisation wasn't worth doing.  Still, it was interesting to
> investigate it, if for no other reason than to see if my gut feeling was
> right.  It turned out that under 1.5.0 it was a total waste of time. 
> Under 1.4.1 your mileage may vary.
> 

Regarding the value of the loop investigation, I can only really point 
to AJ and Adrian's replies.

>>1. Think through your design and choose appropriate algorithms.
>>2. Write clean maintainable code.
>>3. If the application isn't fast enough, profile it.
>>4. Fix the performance bottle necks.
>>5. Go to step 3.
> 
> A fine recommendation, and I don't recall anyone arguing against it when
> others said similar things in this thread.  Exactly what constitutes
> "clean maintainable code" is possibly the real subject of this debate.
> 

Fine.  Except of course that everytime someone tries to emphisise the 
importance of readability, someone else seems to want to respond 
"Readability is important, as long as you minimise heap allocation". 
The sentiment is not only wrong, but seriously harmful.  IF you are 
doing OOP then heap allocation is background noise, not worth thinking 
about.  OTOH if you want to program Java, the whole language from design 
to implementation will oppose any attempt to write use a different paradigm.

Andrae Muys

[0] For those not familiar with it "Premature-optimisation is the root 
of all evil".

[1] Last Call Optimisation, there was a reasonably extensive dsig thread 
on it a month or so ago.

[2] Ok, so my description is out by several orders of magnitude; it 
reads better this way ;)





More information about the General mailing list