You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by Jonathan Valliere <jo...@apache.org> on 2018/10/11 16:07:09 UTC

Java Generics

I was having a conversation with a colleague last week about the cost of
automatic casting due to the use of generics in java; so, I decided to
write a benchmark.  Since everyone wants their networking code to run as
fast as possible, I thought I would share it with all of you.

Feel free to peer-review the code.
https://github.com/jon-valliere/jmh-generics-benchmark

Re: Java Generics

Posted by Jonathan Valliere <jo...@emoten.com>.
I updated the test suite this morning.  There is definitely a correlation
to performance and invokeinterface, however BakedGenericAbstractTest is
using invokevirtual and is actually 2x as expensive as invokeinterface in
that test.

On Fri, Oct 12, 2018 at 4:29 AM Emmanuel Lécharny <el...@gmail.com>
wrote:

>
>
> Le 11/10/2018 à 19:03, Jonathan Valliere a écrit :
> > One explaination I came up was that Java is performing a full upcast when
> > encountering the generic-based interface.  Unchecked and checked genetics
> > perform identically.
>
> Here is the bytecode for the strictMethod() :
>
>  0: aload_0
>  1: invokevirtual   #12  // Method
> createStrictReceiver:()LSimpleInliningTest$ReceiverB;
>  4: astore_1
>  5: aload_0
>  6: invokevirtual   #13  // Method
> createStrictObject:()LSimpleInliningTest$TypeA;
>  9: astore_2
> 10: aconst_null
> 11: astore_3
> 12: iconst_0
> 13: istore          4
> 15: iload           4
> 17: ldc             #4   // int 1000000
> 19: if_icmpeq       48
> 22: aload_3
> 23: aload_2
> 24: if_acmpne       36
> 27: aload_1
> 28: aload_2
> 29: invokevirtual   #14  // Method
>
> SimpleInliningTest$ReceiverB.foo:(LSimpleInliningTest$TypeA;)LSimpleInliningTest$TypeA;
> 32: astore_3
> 33: goto            42
> 36: aload_1
> 37: aload_2
> 38: invokevirtual   #14  // Method
>
> SimpleInliningTest$ReceiverB.foo:(LSimpleInliningTest$TypeA;)LSimpleInliningTest$TypeA;
> 41: astore_3
> 42: iinc            4, 1
> 45: goto            15
> 48: return
>
> and the same for uncheckedMethod():
>
>  0: aload_0
>  1: invokevirtual   #2   // Method
> createUncheckedReceiver:()LSimpleInliningTest$Receiver;
>  4: astore_1
>  5: aload_0
>  6: invokevirtual   #3   // Method
> createUncheckedObject:()Ljava/lang/Object;
>  9: astore_2
> 10: aconst_null
> 11: astore_3
> 12: iconst_0
> 13: istore          4
> 15: iload           4
> 17: ldc             #4   // int 1000000
> 19: if_icmpeq       52
> 22: aload_3
> 23: aload_2
> 24: if_acmpne       38
> 27: aload_1
> 28: aload_2
> 29: invokeinterface #5, 2// InterfaceMethod
> SimpleInliningTest$Receiver.foo:(Ljava/lang/Object;)Ljava/lang/Object;
> 34: astore_3
> 35: goto            46
> 38: aload_1
> 39: aload_2
> 40: invokeinterface #5, 2// InterfaceMethod
> SimpleInliningTest$Receiver.foo:(Ljava/lang/Object;)Ljava/lang/Object;
> 45: astore_3
> 46: iinc            4, 1
> 49: goto            15
> 52: return
>
>
>
> My guess is that the difference coms from the invokevirtual being used
> on one case and invokeinterface in the other (line 29).
>
> invokeinterface seems clearly coslier than invokevirtual.
>
> --
> Emmanuel Lecharny
>
> Symas.com
> directory.apache.org
>
>

Re: Java Generics

Posted by Emmanuel Lécharny <el...@gmail.com>.

Le 11/10/2018 à 19:03, Jonathan Valliere a écrit :
> One explaination I came up was that Java is performing a full upcast when
> encountering the generic-based interface.  Unchecked and checked genetics
> perform identically.

Here is the bytecode for the strictMethod() :

 0: aload_0
 1: invokevirtual   #12  // Method
createStrictReceiver:()LSimpleInliningTest$ReceiverB;
 4: astore_1
 5: aload_0
 6: invokevirtual   #13  // Method
createStrictObject:()LSimpleInliningTest$TypeA;
 9: astore_2
10: aconst_null
11: astore_3
12: iconst_0
13: istore          4
15: iload           4
17: ldc             #4   // int 1000000
19: if_icmpeq       48
22: aload_3
23: aload_2
24: if_acmpne       36
27: aload_1
28: aload_2
29: invokevirtual   #14  // Method
SimpleInliningTest$ReceiverB.foo:(LSimpleInliningTest$TypeA;)LSimpleInliningTest$TypeA;
32: astore_3
33: goto            42
36: aload_1
37: aload_2
38: invokevirtual   #14  // Method
SimpleInliningTest$ReceiverB.foo:(LSimpleInliningTest$TypeA;)LSimpleInliningTest$TypeA;
41: astore_3
42: iinc            4, 1
45: goto            15
48: return

and the same for uncheckedMethod():

 0: aload_0
 1: invokevirtual   #2   // Method
createUncheckedReceiver:()LSimpleInliningTest$Receiver;
 4: astore_1
 5: aload_0
 6: invokevirtual   #3   // Method
createUncheckedObject:()Ljava/lang/Object;
 9: astore_2
10: aconst_null
11: astore_3
12: iconst_0
13: istore          4
15: iload           4
17: ldc             #4   // int 1000000
19: if_icmpeq       52
22: aload_3
23: aload_2
24: if_acmpne       38
27: aload_1
28: aload_2
29: invokeinterface #5, 2// InterfaceMethod
SimpleInliningTest$Receiver.foo:(Ljava/lang/Object;)Ljava/lang/Object;
34: astore_3
35: goto            46
38: aload_1
39: aload_2
40: invokeinterface #5, 2// InterfaceMethod
SimpleInliningTest$Receiver.foo:(Ljava/lang/Object;)Ljava/lang/Object;
45: astore_3
46: iinc            4, 1
49: goto            15
52: return



My guess is that the difference coms from the invokevirtual being used
on one case and invokeinterface in the other (line 29).

invokeinterface seems clearly coslier than invokevirtual.

-- 
Emmanuel Lecharny

Symas.com
directory.apache.org


Re: Java Generics

Posted by Jonathan Valliere <jo...@emoten.com>.
One explaination I came up was that Java is performing a full upcast when
encountering the generic-based interface.  Unchecked and checked genetics
perform identically.

Because the generics are fully removed at compile time; Java may be forced
to do full type casting every time the method is called.

If there isn’t something inherently wrong with the test then there is a big
performance penalty when using generic interfaces.

On Thu, Oct 11, 2018 at 12:50 PM Emmanuel Lécharny <el...@gmail.com>
wrote:

> Thanks, Jonathan,
>
> Le 11/10/2018 à 18:07, Jonathan Valliere a écrit :
> > I was having a conversation with a colleague last week about the cost of
> > automatic casting due to the use of generics in java; so, I decided to
> > write a benchmark.  Since everyone wants their networking code to run as
> > fast as possible, I thought I would share it with all of you.
> >
> > Feel free to peer-review the code.
> > https://github.com/jon-valliere/jmh-generics-benchmark
>
> Running this benchmark, I get a 10x slower run when using generic
> compared to the non-generic version (3G op/s vs 300M op/s)
>
> That beaing said, Generic are't supposed to have any impact on java
> code, because it's all removed by the compiler, so there must be
> something weirdo going on. It would be interesting to check the
> generated bytecode to see the difference.
>
>
> --
> Emmanuel Lecharny
>
> Symas.com
> directory.apache.org
>
>

Re: Java Generics

Posted by Emmanuel Lécharny <el...@gmail.com>.
Thanks, Jonathan,

Le 11/10/2018 à 18:07, Jonathan Valliere a écrit :
> I was having a conversation with a colleague last week about the cost of
> automatic casting due to the use of generics in java; so, I decided to
> write a benchmark.  Since everyone wants their networking code to run as
> fast as possible, I thought I would share it with all of you.
> 
> Feel free to peer-review the code.
> https://github.com/jon-valliere/jmh-generics-benchmark

Running this benchmark, I get a 10x slower run when using generic
compared to the non-generic version (3G op/s vs 300M op/s)

That beaing said, Generic are't supposed to have any impact on java
code, because it's all removed by the compiler, so there must be
something weirdo going on. It would be interesting to check the
generated bytecode to see the difference.


-- 
Emmanuel Lecharny

Symas.com
directory.apache.org