2

In Kotlin, is there a performance cost to empty methods, or are they ignored?

I ran the following test code, and the cost seems negligible:

fun emptyMethod() {}

for(max in listOf(1000, 10000, 100000, 1000000)){
    val start = Instant.now().toEpochMilli()
    for(i in 0..max) {
        emptyMethod()
    }
    val millis= Instant.now().toEpochMilli() - start
    println("$max iterations: $millis millis.")
}

// 1000 iterations: 0 millis.
// 10000 iterations: 0 millis.
// 100000 iterations: 4 millis.
// 1000000 iterations: 10 millis.

I'm doing validation and I want to use an empty method for documentation purposes (ex. petName.mayBeNull()) to avoid future comment rot.

JoseHdez_2
  • 4,040
  • 6
  • 27
  • 44
  • Is there any tool in your IDE which will show you the disassembly? – Matthew Layton Mar 04 '20 at 12:04
  • @MatthewLayton not that I know of, I'm using IntelliJ IDEA. I checked in the marketplace but didn't find any plugins. – JoseHdez_2 Mar 04 '20 at 12:17
  • 1
    Why do you think that empty method calls would be better documentation, or any more rot-proof, than comments? – gidds Mar 04 '20 at 13:05
  • @gidds Glad that you asked :-) In my example, if somebody renames `petName` to `animalCompanion`, or delete the attribute entirely(!), the comment will stay the same. A method call will be updated alongside the attribute name, and will not compile if it's deleted. – JoseHdez_2 Mar 04 '20 at 13:10
  • 1
    I think annotations are better suited for being "structured comments" than calling empty methods. – al3c Mar 04 '20 at 14:06
  • @al3c I agree! Annotations were my first choice; you can iterate through the accessors, the model becomes the SSOT... Sadly I'm generating the Kotlin model from JSON (project constraint) and I would lose all annotations each time I regenerate the model. – JoseHdez_2 Mar 04 '20 at 15:29

1 Answers1

4

In the Kotlin JVM bytecode, the call to an empty function will still be present.

Usually, the compilers that emit JVM bytecode don't run low-level optimizations such as the one you supposed might happen, because:

  • it's useful to to retain the bytecode close to the source code structure for debugging purposes
  • the JIT compilers in JVM implementations and AOT compilers are much better at low-level optimizations, especially since they can take into account the particular architecture

So, whether or not the call to the empty function will have zero cost at runtime is defined by the implementation of the JVM runtime (or AOT compiler) that you use.

You could try to get disassembly from the JIT-compiled code at runtime, but the way to do that is specific to your JVM implementation. For example, with OpenJDK, this can be done with -XX:PrintAssembly option, referenced in this Q&A: Disassemble Java JIT compiled native bytecode

hotkey
  • 140,743
  • 39
  • 371
  • 326