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 Optimize Coroutine invocations

  • spring-boot 3.2.1 with 6.1.5-SNAPSHOT-p1 Spring Optimize Coroutine invocations

  • spring-boot 3.2.1 with 6.1.5-SNAPSHOT-p2 Spring Optimize Coroutine invocations

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 Optimize Coroutine invocations

  • spring-boot 3.2.1 with 6.1.5-SNAPSHOT-p2 Spring Optimize Coroutine invocations

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 ?