kafka-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Michael Andre Pearce (IG) (JIRA)" <j...@apache.org>
Subject [jira] [Comment Edited] (KAFKA-4424) Make serializer classes final
Date Thu, 24 Nov 2016 01:03:58 GMT

    [ 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)

Mime
View raw message