• Home
Name Date Size #Lines LOC

..--

benchmark/04-Jul-2025-373259

core/04-Jul-2025-2,1851,268

demo/04-Jul-2025-1,8001,167

robolectric/04-Jul-2025-3,4602,802

Android.bpD04-Jul-2025677 2018

README.mdD04-Jul-20253.6 KiB12494

README.md

1# Coroutine Tracing
2
3This library contains utilities for tracing coroutines. Coroutines cannot be traced using the
4`android.os.Trace` APIs normally because suspension points will lead to malformed trace sections.
5This is because each `Trace.beginSection()` call must have a matching `Trace.endSection()` call; if
6a coroutine suspends before `Trace.endSection()` is called, the trace section will remain open while
7other unrelated work executes on the thread.
8
9To address this, we introduce a function `traceCoroutine("name") { ... }` that can be used for
10tracing sections of coroutine code. When invoked, a trace section with the given name will start
11immediately, and its name will also be written to an object in thread-local storage which is managed
12by an object in the current `CoroutineContext`, making it safe, "coroutine-local" storage. When the
13coroutine suspends, all trace sections will end immediately. When resumed, the coroutine will read
14the names of the previous sections from coroutine-local storage, and it will begin the sections
15again.
16
17For example, the following coroutine code will be traced as follows:
18
19```
20traceCoroutine("Slice A") {
21  println("Start")
22  delay(10)
23  println("End")
24}
25```
26
27```
28Thread #1 |  [==== Slice ====]          [==== Slice ====]
29               ^ "Start" printed          ^ "End" printed
30```
31
32If multiple threads are used, it would be as follows:
33
34```
35traceCoroutine("Slice") {
36  println("Start")
37  delay(10)
38  withContext(backgroundThread) {
39    println("End")
40  }
41}
42```
43
44```
45Thread #1 |  [==== Slice ====]
46          |    ^ "Start" printed
47----------+---------------------------------------------------------
48Thread #2 |                              [==== Slice ====]
49                                           ^ "End" printed
50```
51
52This library also provides wrappers for some of the coroutine functions provided in the
53`kotlinx.coroutines.*` package.  For example, instead of:
54`launch { traceCoroutine("my-launch") { /* block */ } }`, you can instead write:
55`launchTraced("my-launch") { /* block */ }`.
56
57It also provides a wrapper for tracing `Flow` collections. For example,
58
59```
60val coldFlow = flow {
61  emit(1)
62  emit(2)
63  emit(3)
64}
65
66coldFlow.collect("F") {
67  println(it)
68  yield()
69}
70```
71
72Would be traced as follows:
73
74```
75Thread #1 |  [===== collect:F =====]    [=== collect:F ====]    [===== collect:F =====]
76          |    [= collect:F:emit =]     [= collect:F:emit =]    [= collect:F:emit =]
77          |            ^ "1" printed           ^ "2" printed            ^ "3" printed
78```
79
80# Building and Running
81
82## Host Tests
83
84Host tests are implemented in `tracinglib-host-test`. To run the host tests:
85
86```
87atest tracinglib-host-test
88```
89
90## Feature Flag
91
92Coroutine tracing is flagged off by default. To enable coroutine tracing on a device, flip the flag
93and restart the user-space system:
94
95```
96adb shell device_config override systemui com.android.systemui.coroutine_tracing true
97adb shell am restart
98```
99
100## Extra Debug Flags
101
102The behavior of coroutine tracing can be further fine-tuned using the following sysprops:
103
104 - `debug.coroutine_tracing.walk_stack_override`
105 - `debug.coroutine_tracing.count_continuations_override`
106
107See [`createCoroutineTracingContext()`](core/src/coroutines/TraceContextElement.kt) for
108documentation.
109
110## Demo App
111
112Build and install the app using Soong and adevice:
113
114```
115adevice track CoroutineTracingDemoApp
116m CoroutineTracingDemoApp
117adevice update
118```
119
120Then, open the app and tap an experiment to run it. The experiments run in the background. To see
121the effects of what coroutine tracing is doing, you will need to capture a Perfetto trace. The
122[`coroutine_tracing` flag](#feature-flag) will need to be enabled for coroutine trace sections to
123work.
124