[ 
https://issues.apache.org/jira/browse/KAFKA-4424?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=15691817#comment-15691817
 ] 

Michael Andre Pearce (IG) edited comment on KAFKA-4424 at 11/24/16 1:03 AM:
----------------------------------------------------------------------------

The link you reference re virtual calls.

This is much more about monomorphic call or polymorphic calls. Making a class 
that implements an interface final, where the method invocation is by interface 
methods, does not change this.

This is more to do with the number of class's loaded/invoked that implement the 
interface. 

So in case of single implementation being used and loaded your jvm you have a 
monomorphic case for the interface, the JVM will inline this (final or not).

If you happen to have two implementations being used and loaded the jvm will 
still be able to inline but will create a branch case, the second loaded 
implementation will be slower if invoked due to the branch.

If you have more than two implementations loaded the JVM will on loading these 
do on stack replacement of the previously loaded inlined, and move to using 
virtual(jump) tables.


You'll see this occur if you turn on -XX:+PrintCompilation

A classical implementation/test and write up showing this is:
http://mechanical-sympathy.blogspot.co.uk/2012/04/invoke-interface-optimisations.html

You'll note taking the code in the blog, and running it with or without final 
implementations makes no difference.

Also i've taken this test from the above blog, for your final and non final 
cases (i've attached to this jira), if you note I've uploaded two versions, one 
with the final being declared and loaded by the JVM first and vice versa. As 
you note in both the implementation loaded first due to the inlined branch will 
be more performant.

On checking your original test case we noted that the FinalByteArraySerializer 
version runs first (due to alphabetic ordering that test are run in) , as such 
it would be always the first in the inline branch benefitting from this, this 
would explain why it seems always final was negligible faster when running your 
benchmark test case.



was (Author: michael.andre.pearce):
The link you reference re virtual calls.

This is much more about monomorphic call or polymorphic calls. Making a class 
that implements an interface final, where the method invocation is by interface 
methods, does not change this.

This is more to do with the number of class's loaded/invoked that implement the 
interface. 

So in case of single implementation being used and loaded your jvm you have a 
monomorphic case for the interface, the JVM will inline this (final or not).

If you happen to have two implementations being used and loaded the jvm will 
still be able to inline but will create a branch case, the second loaded 
implementation will be slower if invoked due to the branch.

If you have more than two implementations loaded the JVM will on loading these 
do on stack replacement of the previously loaded inlined, and move to using 
virtual tables.


You'll see this occur if you turn on -XX:+PrintCompilation

A classical implementation/test and write up showing this is:
http://mechanical-sympathy.blogspot.co.uk/2012/04/invoke-interface-optimisations.html

You'll note taking the code in the blog, and running it with or without final 
implementations makes no difference.

Also i've taken this test from the above blog, for your final and non final 
cases (i've attached to this jira), if you note I've uploaded two versions, one 
with the final being declared and loaded by the JVM first and vice versa. As 
you note in both the implementation loaded first due to the inlined branch will 
be more performant.

On checking your original test case we noted that the FinalByteArraySerializer 
version runs first (due to alphabetic ordering that test are run in) , as such 
it would be always the first in the inline branch benefitting from this, this 
would explain why it seems always final was negligible faster when running your 
benchmark test case.


> Make serializer classes final
> -----------------------------
>
>                 Key: KAFKA-4424
>                 URL: https://issues.apache.org/jira/browse/KAFKA-4424
>             Project: Kafka
>          Issue Type: Improvement
>          Components: clients
>            Reporter: Matthias Bechtold
>            Priority: Minor
>         Attachments: FinalTest.java, FinalTestReversed.java
>
>
> Implementations of simple serializers / deserializers should be final to 
> prevent JVM method call overhead.
> See also:
> https://wiki.openjdk.java.net/display/HotSpot/VirtualCalls
> This breaks the API slightly, inheritors must change to generic interfaces 
> Serializer / Deserializer. But architecture-wise final serialization classes 
> make the most sense to me.
> So what do you think?



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to