I had a question regarding performance. I hadn't p...
# announcements
j
I had a question regarding performance. I hadn't previously noticed that a field access in kotlin seems to be always via an accessor method. For example a public field Bob.t referenced as b.t in some file will invokevirtual Bob.getT which returns getfield Bob.t - in the case where t is got a lot this can affect performance quite a bit. Turning a data class from kotlin to a simple java object with final immutable fields changes this to getfield and so saves the indirection. Is there a way to prefer field access?
j
if Bob.t is got a lot, then the JIT will inline the call. This problem has been solved for a long time with JavaBean-like objects in Java, which are used everywhere, and Kotlin data clases are just that. So I wouldn’t worry about it. Performance problems will be elsewhere.
👌 2
t
There's the @JvmField annotation. When applied to a public property, it'll be generated as a Java field with no getter method. Note that the performance boost is likely to be unsignificant: the getter/setter pattern is so common that most JVM runtimes optimize it out.
j
Changing the file from a data class to a java object using field access has improved performance by 21% in my usecase. The jit doesn't appear to make that field access. This is running under java 11 on x64.
Thanks for the suggestion about jvmfield!
The jvmfield annotations result the same bytecode as the java class approach. So, thank you for that suggestion. I admit not all programs have this access pattern, but when invoking method 257m times, worth looking at the bytecode....
t
Out of curiosity, how are you benchmarking?
j
I'm just running my program. Previously, after warming up, it renders some scene in 1.68 seconds, after the jvmfield change it renders in 1.32 seconds, with that being the only change. The timings are very stable.
By the way, and not wanting to come across negativly, the jit didn't sort it out, and the performance issue wasn't elsewhere. It was exactly there, and I did want to worry about it.
y
That 0.36 second difference might be the time it took for the jit to inline every single call site if you have multiple call sites. I'd heavily suggest that you try rerendering the scene multiple times in a row and see what will happen, or use a proper benchmarking tool to test the different between getter vs field access over a stable set of millions of calls.
h
It would be very interesting what prevents jit from inlining in your usecase, if it's at all prevented :) i look at those problems from time to time myself, developing games stuff
j
Yeah, I'm not suggesting that it isn't. I'm not even suggesting that after some period of time the performance of the two approaches might tend to be the same. However.. it does seem that for some duration of runtime, which is actually about the length of time that the program does actually run for, using a field seems to give faster results in this particular case. I'm not suggesting that this is a generic result that will hold for all programs, thats why I ran it under a profiler for a long time first before even posting my initial question...
So the question was: how to prefer field access, and I'm really happy that it was answered, but people saying - "you don't know what you are doing" isn't actually that helpful
y
Oh I didn't mean a "you don't know what you are doing" at all and I'm sorry if it came off that way. I was just trying to figure out how you got this result because it peaked my interest. The @JvmField annotation is definitely the better option in this case, but I was just wondering why that's the case especially since in the future you might need actual getters and setters if your use case changes
j
No worries. Appreciate that. For the most part I dont really use "setters", for lots of reasons, but in this case the data is immutable so access patterns probably won't change.
e
if you use tools like ProGuard or R8, they can inline methods like that (by changing the backing field's visibility as well)