On Mon, 2002-11-11 at 10:18, Peter B. West wrote:
> Jeremias,
> 
> This was a serious question, really.  Joerg, when he gets back, might 
> like to comment on this, because it was as a result of some of his input 
> that I first realised there was a significant cost associated with such 
> Java fundamentals as instanceof and type casting.  Those discussions 
> gave me much food for thought.  So I'll rephrase the question: what, if 
> anything, is the cost of using the interface instead of the implementation?

There is very little difference between casting and the instanceof
operator. Both are a single op in the bytecode (use javap to look at the
generated byte code). The speed of the operations are largely determined
by the vm (no shit sherlock :)).

For a look at the op codes here is a cheesy bit of code.

public class Casting
{
    public void test()
    {
        Cast1 testInstance = new Cast2();

        if (testInstance instanceof Cast2)
            {
                System.out.println("Instance of Cast2");
            }
        
        // cast to subclass
        Cast2 subClassVersion = (Cast2) testInstance;

        // cast to interface
        CastInterface interfaceFromCast1Version = (CastInterface) testInstance;

        // cast to interface from implementing class
        CastInterface interfaceFromCast2Version = subClassVersion;
        
        testInstance = subClassVersion;
    }

    public interface CastInterface
    {
        CastInterface getInstance();
    }

    public static class Cast1
    {
        public String foo;
    }

    public static class Cast2 extends Cast1 implements CastInterface
    {
        public CastInterface getInstance()
        {
            return this;
        }
    }
}

and the resulting bytecode for the test method


Method void test()
   0 new #2 <Class Casting. Cast2>
   3 dup
   4 invokespecial #3 <Method Casting. Cast2()>
   7 astore_1
   8 aload_1
   9 instanceof #2 <Class Casting. Cast2>
  12 ifeq 23
  15 getstatic #4 <Field java.io.PrintStream out>
  18 ldc #5 <String "Instance of Cast2">
  20 invokevirtual #6 <Method void println(java.lang.String)>
  23 aload_1
  24 checkcast #2 <Class Casting. Cast2>
  27 astore_2
  28 aload_1
  29 checkcast #7 <Interface Casting. CastInterface>
  32 astore_3
  33 aload_2
  34 astore 4
  36 aload_2
  37 astore_1
  38 return


op 8 - 12 deal with the instanceof test
op 23 - 27 are the class cast
op 28 - 32 are the interface cast
op 33 - 34 are the interface assign
op 36 - 37 are the class assign

the casting operations invoke one extra opcode.

Castiong and Performace

The pattern I use is to expose the objects via their interface but 
internal method access the implementation class. This allows external
use without casting, leave me to decide which concrete implementation is
more applicable. A good example of this is ArrayList vs LinkedList;
simply expose List and determine the concrete class that is suited to
the situation, if you get it wrong you can replace the concrete without
violating your external contracts. 

Because java lacks templates (bring on 1.5) there will always be a cost
associated with generic collection usage (in most cases you have to cast
to get access to the information you want).

The only place I take a second look at casting then is in large loops
(where the negative opcode jump usually costs a lot more than the cast)

instanceof usage always worries me a little, it can be an indication
that there is a problem in encapsulation and interface provision. The 
most common usage is when the interface is used as a marker interface
(eg serializable). The "correctness" of this is a point that can be
debated.

I've seen people skipping the instanceof check and doing a speculative
cast and empty catch. On older vms this was sometimes faster, in my
recent tests this is not the case. My advice, don't do it.  

Optimization - know the outcomes but leave it until the end.

When you code, understand what a cast will do, understand how to use
StringBuffers and Strings, don't apply an optimization unless it's
blatantly obvious.

I've seem many cases where developers have heard that something is a
performance problem, heard about the solution then apply that solution
everywhere without understanding the performance issue. Often this leads
to no improvement in speed but always leads to increased problems in
code maintenance (StringBuffer usage is a classic example).

When you do optimize do it with a profiler and profile a couple of vms.
What is an improvement in one is not always an improvement in the other.
Unwinding loops will usually come well before casting.

Enough rambling about casting and one final point on interfaces. Use
them on every published method you can. They will allow you to tune the
internals of your class without effecting the published contract.

-k.

> Peter
> 
> Peter B. West wrote:
>  > Jeremias,
>  >
>  > I have no objection at all, as long as it costs nothing.  It is free,
>  > isn't it?
>  >
>  > Jeremias Maerki wrote:
>  >
>  >> Fellow FOP developers,
>  >>
>  >> would you mind using the interface instead of the implementation where
>  >> possible? Map instead of HashMap, List instead of ArrayList. I've seen
>  >> this habit in a number of places and not only by Keiron! I've made it a
>  >> habit to follow this pattern
> 
> -- 
> Peter B. West  [EMAIL PROTECTED]  http://www.powerup.com.au/~pbwest/
> "Lord, to whom shall we go?"
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [EMAIL PROTECTED]
> For additional commands, email: [EMAIL PROTECTED]
> 
-- 
If you don't test then your code is only a collection of bugs which 
apparently behave like a working program. 

Website: http://www.rocketred.com.au/blogs/kevin/


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, email: [EMAIL PROTECTED]

Reply via email to