[ 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 12:57 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 tables. You'll see this occur if you turn on -XX:+PrintCompilation A classical implementation and write up showing this is: http://mechanical-sympathy.blogspot.co.uk/2012/04/invoke-interface-optimisations.html You'll note taking the code, and running it with or without final implementations makes no difference. Also i've taken this classical test, for your final and non final cases (attached to this jira), if you note I've loaded 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 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 and write up showing this is: http://mechanical-sympathy.blogspot.co.uk/2012/04/invoke-interface-optimisations.html You'll note taking the code, and running it with or without final implementations makes no difference. Also i've taken this classical test, for your final and non final cases (attached to this jira), if you note I've loaded 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)