Skip to content

Commit 23649ba

Browse files
committed
Disable DebugProbes.enableCreationStackTraces by default
* Adjust tests and the documentation * Rationale: this option implies significant and non-trivial overhead yet its utility is unclear (e.g. we got a multitude of signals that this option brings no use and none that it's useful even when asked explicitly) Fixes #3783
1 parent 761bdeb commit 23649ba

11 files changed

+118
-138
lines changed

kotlinx-coroutines-core/jvm/src/debug/internal/DebugProbesImpl.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ internal object DebugProbesImpl {
4040
private val sequenceNumber = atomic(0L)
4141

4242
internal var sanitizeStackTraces: Boolean = true
43-
internal var enableCreationStackTraces: Boolean = true
43+
internal var enableCreationStackTraces: Boolean = false
4444
public var ignoreCoroutinesWithEmptyContext: Boolean = true
4545

4646
/*

kotlinx-coroutines-debug/README.md

-10
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,6 @@ Coroutine "coroutine#2":DeferredCoroutine{Active}@289d1c02, state: SUSPENDED
123123
at ExampleKt.combineResults(Example.kt:11)
124124
at ExampleKt$computeValue$2.invokeSuspend(Example.kt:7)
125125
at ExampleKt$main$1$deferred$1.invokeSuspend(Example.kt:25)
126-
at _COROUTINE._CREATION._(CoroutineDebugging.kt)
127-
at kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)
128-
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:25)
129-
at kotlinx.coroutines.BuildersKt.async$default(Unknown Source)
130-
at ExampleKt$main$1.invokeSuspend(Example.kt:25)
131-
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)
132-
at kotlinx.coroutines.DispatchedTask.run(Dispatched.kt:233)
133-
at kotlinx.coroutines.BuildersKt.runBlocking$default(Unknown Source)
134-
at ExampleKt.main(Example.kt:23)
135-
at ExampleKt.main(Example.kt)
136126
137127
... More coroutines here ...
138128

kotlinx-coroutines-debug/src/DebugProbes.kt

+3-4
Original file line numberDiff line numberDiff line change
@@ -65,12 +65,11 @@ public object DebugProbes {
6565

6666
/**
6767
* Whether coroutine creation stack traces should be captured.
68-
* When enabled, for each created coroutine a stack trace of the current
69-
* thread is captured and attached to the coroutine.
68+
* When enabled, for each created coroutine a stack trace of the current thread is captured and attached to the coroutine.
7069
* This option can be useful during local debug sessions, but is recommended
71-
* to be disabled in production environments to avoid stack trace dumping overhead.
70+
* to be disabled in production environments to avoid performance overhead of keeping debug probes enabled.
7271
*
73-
* `true` by default.
72+
* `false` by default.
7473
*/
7574
public var enableCreationStackTraces: Boolean
7675
get() = DebugProbesImpl.enableCreationStackTraces

kotlinx-coroutines-debug/test/CoroutinesDumpTest.kt

+7
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package kotlinx.coroutines.debug
22

33
import kotlinx.coroutines.testing.*
44
import kotlinx.coroutines.*
5+
import org.junit.*
56
import org.junit.Test
67
import kotlin.coroutines.*
78
import kotlin.test.*
@@ -10,6 +11,12 @@ class CoroutinesDumpTest : DebugTestBase() {
1011
private val monitor = Any()
1112
private var coroutineThread: Thread? = null // guarded by monitor
1213

14+
@Before
15+
override fun setUp() {
16+
super.setUp()
17+
DebugProbes.enableCreationStackTraces = true
18+
}
19+
1320
@Test
1421
fun testSuspendedCoroutine() = runBlocking {
1522
val deferred = async(Dispatchers.Default) {

kotlinx-coroutines-debug/test/DebugProbesTest.kt

+23-36
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ class DebugProbesTest : DebugTestBase() {
1818
val deferred = createDeferred()
1919
val traces = listOf(
2020
"java.util.concurrent.ExecutionException\n" +
21-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
22-
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
23-
"\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:49)\n" +
24-
"\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:44)\n" +
25-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsync\$1.invokeSuspend(DebugProbesTest.kt:17)\n",
21+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
22+
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
23+
"\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:49)\n" +
24+
"\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:44)\n" +
25+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsync\$1.invokeSuspend(DebugProbesTest.kt:17)\n",
2626
"Caused by: java.util.concurrent.ExecutionException\n" +
27-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
28-
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)"
27+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:14)\n" +
28+
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)"
2929
)
3030
nestedMethod(deferred, traces)
3131
deferred.join()
@@ -38,25 +38,15 @@ class DebugProbesTest : DebugTestBase() {
3838
val deferred = createDeferred()
3939
val traces = listOf(
4040
"java.util.concurrent.ExecutionException\n" +
41-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
42-
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
43-
"\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt)\n" +
44-
"\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt)\n" +
45-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:62)\n" +
46-
"\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
47-
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)\n" +
48-
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt)\n" +
49-
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable\$default(Cancellable.kt)\n" +
50-
"\tat kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt)\n" +
51-
"\tat kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt)\n" +
52-
"\tat kotlinx.coroutines.BuildersKt__BuildersKt.runBlocking(Builders.kt)\n" +
53-
"\tat kotlinx.coroutines.BuildersKt.runBlocking(Unknown Source)\n" +
54-
"\tat kotlinx.coroutines.testing.TestBase.runTest(TestBase.kt)\n" +
55-
"\tat kotlinx.coroutines.testing.TestBase.runTest\$default(TestBase.kt)\n" +
56-
"\tat kotlinx.coroutines.debug.DebugProbesTest.testAsyncWithProbes(DebugProbesTest.kt)",
41+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
42+
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
43+
"\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt)\n" +
44+
"\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt)\n" +
45+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:62)",
5746
"Caused by: java.util.concurrent.ExecutionException\n" +
58-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
59-
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)\n")
47+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt)\n" +
48+
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt)\n"
49+
)
6050
nestedMethod(deferred, traces)
6151
deferred.join()
6252
}
@@ -69,18 +59,15 @@ class DebugProbesTest : DebugTestBase() {
6959
val deferred = createDeferred()
7060
val traces = listOf(
7161
"java.util.concurrent.ExecutionException\n" +
72-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
73-
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
74-
"\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:71)\n" +
75-
"\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:66)\n" +
76-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithSanitizedProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:87)\n" +
77-
"\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
78-
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt:116)\n" +
79-
"\tat kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:23)\n" +
80-
"\tat kotlinx.coroutines.debug.DebugProbesTest.testAsyncWithSanitizedProbes(DebugProbesTest.kt:38)",
62+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
63+
"\tat _COROUTINE._BOUNDARY._(CoroutineDebugging.kt)\n" +
64+
"\tat kotlinx.coroutines.debug.DebugProbesTest.oneMoreNestedMethod(DebugProbesTest.kt:71)\n" +
65+
"\tat kotlinx.coroutines.debug.DebugProbesTest.nestedMethod(DebugProbesTest.kt:66)\n" +
66+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$testAsyncWithSanitizedProbes\$1\$1.invokeSuspend(DebugProbesTest.kt:87)",
8167
"Caused by: java.util.concurrent.ExecutionException\n" +
82-
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
83-
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n")
68+
"\tat kotlinx.coroutines.debug.DebugProbesTest\$createDeferred\$1.invokeSuspend(DebugProbesTest.kt:16)\n" +
69+
"\tat kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:32)\n"
70+
)
8471
nestedMethod(deferred, traces)
8572
deferred.join()
8673
}

kotlinx-coroutines-debug/test/DebugTestBase.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ open class DebugTestBase : TestBase() {
1616
open fun setUp() {
1717
before()
1818
DebugProbes.sanitizeStackTraces = false
19-
DebugProbes.enableCreationStackTraces = true
19+
DebugProbes.enableCreationStackTraces = false
2020
DebugProbes.install()
2121
}
2222

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
package kotlinx.coroutines.debug
2+
3+
import kotlinx.coroutines.*
4+
import org.junit.*
5+
import org.junit.Test
6+
import kotlin.test.*
7+
8+
class DumpWithCreationStackTraceTest : DebugTestBase() {
9+
@Before
10+
override fun setUp() {
11+
super.setUp()
12+
DebugProbes.enableCreationStackTraces = true
13+
}
14+
15+
@Test
16+
fun testCoroutinesDump() = runTest {
17+
val deferred = createActiveDeferred()
18+
yield()
19+
verifyDump(
20+
"Coroutine \"coroutine#1\":BlockingCoroutine{Active}@70d1cb56, state: RUNNING\n" +
21+
"\tat java.lang.Thread.getStackTrace(Thread.java)\n" +
22+
"\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.enhanceStackTraceWithThreadDumpImpl(DebugProbesImpl.kt)\n" +
23+
"\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutinesSynchronized(DebugProbesImpl.kt)\n" +
24+
"\tat kotlinx.coroutines.debug.internal.DebugProbesImpl.dumpCoroutines(DebugProbesImpl.kt)\n" +
25+
"\tat kotlinx.coroutines.debug.DebugProbes.dumpCoroutines(DebugProbes.kt:182)\n" +
26+
"\tat kotlinx.coroutines.debug.StacktraceUtilsKt.verifyDump(StacktraceUtils.kt)\n" +
27+
"\tat kotlinx.coroutines.debug.StacktraceUtilsKt.verifyDump\$default(StacktraceUtils.kt)\n" +
28+
"\tat kotlinx.coroutines.debug.DumpWithCreationStackTraceTest\$testCoroutinesDump\$1.invokeSuspend(DumpWithCreationStackTraceTest.kt)\n" +
29+
"\tat _COROUTINE._CREATION._(CoroutineDebugging.kt)\n" +
30+
"\tat kotlin.coroutines.intrinsics.IntrinsicsKt__IntrinsicsJvmKt.createCoroutineUnintercepted(IntrinsicsJvm.kt)",
31+
32+
"Coroutine \"coroutine#2\":DeferredCoroutine{Active}@383fa309, state: SUSPENDED\n" +
33+
"\tat kotlinx.coroutines.debug.DumpWithCreationStackTraceTest\$createActiveDeferred\$1.invokeSuspend(DumpWithCreationStackTraceTest.kt)"
34+
)
35+
deferred.cancelAndJoin()
36+
}
37+
38+
39+
private fun CoroutineScope.createActiveDeferred(): Deferred<*> = async {
40+
suspendingMethod()
41+
assertTrue(true)
42+
}
43+
44+
private suspend fun suspendingMethod() {
45+
delay(Long.MAX_VALUE)
46+
}
47+
}

kotlinx-coroutines-debug/test/DumpWithoutCreationStackTraceTest.kt

-42
This file was deleted.

0 commit comments

Comments
 (0)