Hi. I'm profiling some coroutine code, and findin...
# coroutines
m
Hi. I'm profiling some coroutine code, and finding suprising results, which I'd like to sense check around Coroutines / Flow's use of exceptions. According to YoutKit profiler, we have 2 hotspots in our code - which all point to
result.throwOnFailure
This code is counting for nearly 93% of our CPU time when we're under load. I've debugged, and see the error getting thrown are: `kotlinx.coroutines.flow.internal.ChildCancelledException`:
Child of the scoped flow was cancelled
(which is designed not to populate the stack trace -- good thing)
kotlinx.coroutines.flow.internal.AbortFlowException
Flow was aborted, no more elements needed -
(appears as though it does capture the stack, not 100% sure though). Assuming the root cause is that we're misusing the framework somehow, It's not obvious to me where these errors are being generated in our code. Anyone had experience with this, or got pointers on how to improve this?
r
Have you got
kotlinx.coroutines.debug
enabled or
-ea
?
Copy code
internal actual class AbortFlowException actual constructor(
    @JvmField @Transient actual val owner: FlowCollector<*>
) : CancellationException("Flow was aborted, no more elements needed") {

    override fun fillInStackTrace(): Throwable {
        if (DEBUG) return super.fillInStackTrace()
        // Prevent Android <= 6.0 bug, #1866
        stackTrace = emptyArray()
        return this
    }
}

internal actual class ChildCancelledException : CancellationException("Child of the scoped flow was cancelled") {
    override fun fillInStackTrace(): Throwable {
        if (DEBUG) return super.fillInStackTrace()
        // Prevent Android <= 6.0 bug, #1866
        stackTrace = emptyArray()
        return this
    }
}
The stack traces appear to only be captured when the system is running in debug mode, which is not recommended for prod, but you may have enabled while profiling?
m
It's possible - I'm launching through IntelliJ - I don't have that explicitly set, but it's possible IntelliJ is "helping" me by adding it. (I went searching for this earlier, as I was also seeing some Coroutine Debug stuff in the proflier)
I don't have it set in the Environment variables, or passed as a VM Option or program argument, but it's possible it is being turned on somewhere
r
Copy code
println(MyClass::class.java.desiredAssertionStatus())
println(System.getProperty(DEBUG_PROPERTY_NAME))
Should be able to indicate if either are enabled
m
Copy code
false
null
So, I guess not
Which is a shame, because that would certainly explain a lot.
r
It's been a long while since I used YourKit but I've found the built in intellij profiler flame graph very useful for tracking down performance problems
m
Yeah,agreed. I'm flip-flopping between both to try and track this down.