KClass instantiation in CoroutinesUtils is suboptimal, and should be replaced by KTypes#isSubtypeOf checks using pre-instantiated types for Flow, Mono and Publisher.
Comment From: sdeleuze
This commit impact on performances is significant since a throughput increase between 2x and 3x has been measured on basic endpoints.
Comment From: sdeleuze
@koo-taejin @efemoney Please test the latest 6.1.5-SNAPSHOT builds and report if you see some unexpected side effects.
Comment From: efemoney
Tested from my side & passes all my tests 👍🏾 just like the previous snapshot
Comment From: koo-taejin
I am going to test it. 👍 thanks :)
Comment From: koo-taejin
Unfortunately, I don't think the situation has changed much. It would be accurate to put it into production and test it, but I apologize for not being able to do this.
Method of getClassifier()has been replaced by method of getJvmErasure().
I had checked that getClassifier() is called from getJvmErasure().
(in org.springframework.core.CoroutinesUtils.lambda$invokeSuspendingFunction$2(Object[], KFunction, Object, CoroutineScope, Continuation))
- spring-boot 3.2.0
-
spring-boot 3.2.1 with
6.1.5-SNAPSHOT-p1 -
spring-boot 3.2.1 with
6.1.5-SNAPSHOT-p2
Also, in the latest version, the isSubTypeOf() method uses resources.
(in org.springframework.core.CoroutinesUtils#invokeSuspendingFunction(kotlin.coroutines.CoroutineContext, java.lang.reflect.Method, java.lang.Object, java.lang.Object...))
- spring-boot 3.2.1 with 6.1.5-SNAPSHOT-p1
- spring-boot 3.2.1 with
6.1.5-SNAPSHOT-p2
This is called for every suspend function, so more use Coroutines, the bigger the impact seems to be.
If there is anything I can do to help, please let me know.
Thank you so much. 🙇
Comment From: sdeleuze
See this related comment.
Comment From: vlsi
I wonder if https://docs.oracle.com/javase/8/docs/api/java/lang/ClassValue.html could help with caching the subtype check (or even ReflectJvmMapping.getKotlinFunction and KotlinDetector.isSuspendingFunction).
In other words, it could pre-compute the reflection analysis so the runtime does not pay the same overhead for every execution.
I had a somewhat similar case in Apache JMeter, and ClassValue did help there: https://github.com/apache/jmeter/blob/91ed1279438cbc2553121c8ea1afded0605b38e5/src/core/src/main/java/org/apache/jmeter/testbeans/TestBeanHelper.java#L88
Comment From: sdeleuze
@vlsi Thanks for sharing, I can explore this, any chance you could create a related new issue ?