  This paper addresses the challenge of understanding the waiting dependencies
between the threads and hardware resources required to complete a task. The
objective is to improve software performance by detecting the underlying
bottlenecks caused by system-level blocking dependencies. In this paper, we use
a system level tracing approach to extract a Waiting Dependency Graph that
shows the breakdown of a task execution among all the interleaving threads and
resources. The method allows developers and system administrators to quickly
discover how the total execution time is divided among its interacting threads
and resources. Ultimately, the method helps detecting bottlenecks and
highlighting their possible causes. Our experiments show the effectiveness of
the proposed approach in several industry-level use cases. Three performance
anomalies are analysed and explained using the proposed approach. Evaluating
the method efficiency reveals that the imposed overhead never exceeds 10.1%,
therefore making it suitable for in-production environments.
