Is reflection slowing down your code? <https://kt....
# feed
m
Is reflection slowing down your code? https://kt.academy/article/benchmark-reflection
๐Ÿ“Š 4
๐Ÿ‘ 2
yes black 7
s
When I was a trainee, my supervisor gave me a piece of advice about reflection: "Don't." ๐Ÿ˜„ It's great to see the numbers put into perspective. Everyone knows synchronization is slow, but it's interesting to learn that it has the same performance impact as reflection. Printing, on the other hand, is remarkably expensive. I knew it had a cost, but I didn't realize it was that significant. Time to go clean up some of those debug logs...
m
Thank you, when I started reading your comment I though you made a summary, but it just seems we have similar experiences ๐Ÿ˜„
s
I avoid reflection whenever possible. There was a time when everything relied on reflectionโ€”not only is it slow, but it can also be challenging to debug. Instead, I prefer using generated proxy classes, like those provided by SQLDelight.
r
I still maintain a Java application, created almost 25 years ago, which is literally "reflection-based" ๐Ÿ™‚ It still works "good enough" and is still sold to new customers ๐Ÿ˜‰ So let's not forget that everything has its bad and good sides ๐Ÿ™‚
๐Ÿ‘ 8
s
Yes, of course. Reflection allows to write really flexible solutions with less code. I try to avoid it because I want my apps to be as fast as possible. So if there is a way to make something faster I usually go for the extra work.
โž• 1
e
Kotlin reflection does have some initialization cost, although that will get amortized over the runtime of an application
๐Ÿ‘ 1
it's also missing a comparison with
Copy code
@Benchmark
fun javaMethodHandles(bh: Blackhole, counter: Counter) {
    val increment = MethodHandles.lookup().findSpecial(Counter::class.java, "increment", MethodType.methodType(Int::class.java), Counter::class.java)
    val decrement = MethodHandles.lookup().findSpecial(Counter::class.java, "decrement", MethodType.methodType(Int::class.java), Counter::class.java)
    val get = MethodHandles.lookup().findSpecial(Counter::class.java, "get", MethodType.methodType(Int::class.java), Counter::class.java)
    repeat(1_000_000) {
        increment.invokeExact(counter) as Int
        decrement.invokeExact(counter) as Int
        increment.invokeExact(counter) as Int
        get.invokeExact(counter) as Int
    }
    bh.consume(counter)
}
which is about twice as fast as Java reflection, within about 50% of a regular method call
๐Ÿ‘€ 1
d
More than slowing down my code, it slows down my development (eventually). It might make things easier at first, but as requirement complexity grows, reflection based code often becomes a hindrance.
โž• 2
e
it depends. I find our reflection-based code to be easier to maintain than our bytecode-manipulation code or most of our code generation. none of it is easy though
s
bytecode manipulation is another thing I seek to avoid ๐Ÿ˜„
p
I've get rid of reflection at all when create compiler plugin for such stuff. With Kotlin compiler plugin it is relatively easy to make such flexibility that reflection provides, and keep performance of no reflection code.
๐Ÿ‘ 2
s
That was my point about SQLDelight ๐Ÿ˜„
e
for now the maintenance experience of plugins is even worse than the other options imo. of course there are some things that can only be done that way though
and sqldelight isn't a compiler plugin
s
Ah, ok.
m
Why does nobody mention the problems which reflection introduces into static code analysis and code reduction?
๐Ÿ‘ 2