How we built an async-aware Python profiler | Datadog
Sep 30, 2026Thomas Kowalski, Scott Gerring

Summary
This post details the development of an async-aware Python profiler. It explains how asyncio's execution model (coroutines, tasks, event loop) differs from synchronous code, leading to flattened flame graphs that obscure task relationships. The solution reconstructs these relationships by tracking parent-child task dependencies and building a task dependency tree to create 'stacked stacks'. It also addresses edge cases like tasks outliving their creators and discusses overhead reduction techniques, achieving over 60% reduction.
More from the Java CPU Profiling trail
- Unbiased Java CPU profiling with JFR in JDK 25 | Datadog
- From hand-tuned Go to self-optimizing code: Building BitsEvolve | Datadog
- How we tracked down a Go 1.24 memory regression across hundreds of pods | Datadog
- .NET Continuous Profiler: Exception and lock contention | Datadog
- .NET Continuous Profiler: CPU and wall time profiling | Datadog