Repository navigation
Description
Context
Validating runtime 0.1.0-ALPHA01 tracing on Android (API 35 emulator, PoC: santimattius/android-coroutine-storm#1). I recorded Perfetto traces for three scenarios (unbounded fan-out, hand-rolled bounded, parallel(concurrency = 4)) using DefaultDispatcherProvider.traced(AndroidTraceSink()).
The structured.<label>.pending / .running counter tracks work as documented and clearly show starvation in the unbounded case (peak pending 1997, ~1.6 s above 100). Three gaps made the traces harder to use than the README suggests.
Findings
1. withTraceSpan names never reach the system trace
AndroidTraceSink emits only slices named <label> or <label>:<CoroutineName>. Spans opened with withTraceSpan("checkout") { } do not appear, and there are no flows linking related segments. As a workaround the PoC adds a CoroutineName per scenario (io:storm-bounded).
2. Queue delay is not exported
Slices carry no args, so queueDelayNanos / queue_delay_ns cannot be queried in Perfetto. pending is the only queueing signal in the trace; actual delay had to come from the app's own instrumentation.
3. running counter semantics
running counts dispatched runnables, not logical task concurrency. With parallel(4) it peaked at 10 while real work never exceeded 4 (a unit test asserts this). It cannot be read as "permits in use". Not a bug, but the README should say so.
Proposal
- Emit
withTraceSpannames as slices (orTrace.beginAsyncSection, so spans survive thread hops) and link the segments of a span, so a span is visible end to end. - Attach queue delay to each slice as an arg, or expose it as a counter, when the sink level allows it.
- Document the
runningsemantics, and the<label>:<CoroutineName>slice naming, in the runtime README tracing section.
Evidence (PoC measurements)
| Metric | unbounded | bounded | parallel(4) |
|---|---|---|---|
| Peak pending | 1997 | 2 | 17 |
| Peak running | 4 | 4 | 10 |
| Max queue delay (app instrumentation) | 1428 ms | 0 ms | 20 ms |
| Worker threads used | 4 | 4 | 28 |
| Dispatch slices | 2000 | 4 | 3998 |
Acceptance criteria
- A
withTraceSpanblock is visible in a Perfetto trace by name, across thread hops. - Queue delay is queryable from the trace (arg or counter), gated by trace level.
- README tracing section documents slice naming and
runningsemantics. - Test or sample trace shows the above on Android.
Related: #167
Activity
santimattius commentedon Nov 2, 2026
Resolved by #169 and #171.
withTraceSpanis visible by name across thread hops:AndroidTraceSinknow emits one async slicespan:<name>per span (feat(runtime): export span and queue delay through AndroidTraceSink #169, system trace, API 29+).structured.<label>.queue_delay_usandqueue_delay_max_uscounters (feat(runtime): export span and queue delay through AndroidTraceSink #169). Per-slice args and span flows are available throughPerfettoTraceSinkon Android (feat(runtime-tracing): support Android and release 0.1.0-ALPHA02 #171,:runtime-tracing, androidx.tracing 2.0.5).runningsemantics and the differences between both sinks.android.os.Tracehas no slice args or flows, so those need the androidx.tracing sink, which records into the in-process buffer and is merged with the system trace afterwards.Available in runtime
0.1.0-ALPHA02once released.