Skip to content

Conversation

@vlad-scherbich
Copy link
Contributor

@vlad-scherbich vlad-scherbich commented Dec 8, 2025

https://datadoghq.atlassian.net/browse/PROF-12724

Description

Adds profiling support for asyncio.Condition to the Python Lock profiler. This extends the lock profiling capability to include condition variables in asynchronous applications.

Motivation

asyncio.Condition is a synchronization primitive that allows tasks to wait for a specific condition. Profiling Condition usage helps identify:

  • Contention points where tasks are waiting on conditions
  • Long wait times in producer/consumer patterns
  • Potential bottlenecks in async coordination logic

Changes

  1. New Collector: Added AsyncioConditionCollector in ddtrace/profiling/collector/asyncio.py.
  2. Internal Lock Detection: asyncio.Condition also creates an internal asyncio.Lock, and since we now have a handful of lock types following the same pattern, the is_internal logic was generalized by adding a INTERNAL_MODULE_FILE class attribute to LockCollector.

Testing

  • Added TestAsyncioConditionCollector with test_condition_wait_notify test
  • Inherits base tests from BaseAsyncioLockCollectorTest

@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

CODEOWNERS have been resolved as:

releasenotes/notes/Added-support-for-profiling-of-asyncio.BoundedSemaphore-objects-to-the-Python-Lock-profiler-5bf06391b0b047f1.yaml  @DataDog/apm-python
releasenotes/notes/Added-support-for-profiling-of-asyncio.Condition-objects-to-the-Python-Lock-profiler-26eee0eb-4831-4c.yaml  @DataDog/apm-python
releasenotes/notes/Added-support-for-profiling-of-asyncio.Semaphore-objects-to-the-Python-Lock-profiler-193fd8150d084ea6.yaml  @DataDog/apm-python
ddtrace/profiling/collector/_lock.py                                    @DataDog/profiling-python
ddtrace/profiling/collector/asyncio.py                                  @DataDog/profiling-python
ddtrace/profiling/profiler.py                                           @DataDog/profiling-python
tests/profiling/collector/test_asyncio.py                               @DataDog/profiling-python
tests/profiling/test_profiler.py                                        @DataDog/profiling-python

@github-actions
Copy link
Contributor

github-actions bot commented Dec 8, 2025

Bootstrap import analysis

Comparison of import times between this PR and base.

Summary

The average import time from this PR is: 251 ± 3 ms.

The average import time from base is: 265 ± 7 ms.

The import time difference between this PR and base is: -14.1 ± 0.2 ms.

Import time breakdown

The following import paths have shrunk:

ddtrace.auto 9.492 ms (3.79%)
ddtrace 5.279 ms (2.11%)
ddtrace._logger 3.265 ms (1.30%)
ddtrace.internal.telemetry 2.945 ms (1.18%)
ddtrace.internal.telemetry.writer 2.086 ms (0.83%)
ddtrace.internal.utils.version 0.932 ms (0.37%)
ddtrace.version 0.760 ms (0.30%)
ddtrace.vendor.packaging.version 0.172 ms (0.07%)
ddtrace.vendor.packaging._structures 0.030 ms (0.01%)
ddtrace.internal.packages 0.436 ms (0.17%)
ddtrace.internal.module 0.219 ms (0.09%)
ddtrace.internal.wrapping.context 0.178 ms (0.07%)
ddtrace.internal.wrapping 0.157 ms (0.06%)
bytecode 0.123 ms (0.05%)
bytecode.bytecode 0.087 ms (0.03%)
bytecode.flags 0.087 ms (0.03%)
bytecode.instr 0.087 ms (0.03%)
bytecode.cfg 0.036 ms (0.01%)
bytecode.concrete 0.036 ms (0.01%)
contextvars 0.021 ms (0.01%)
_contextvars 0.021 ms (0.01%)
_sysconfigdata__linux_x86_64-linux-gnu 0.077 ms (0.03%)
sysconfig 0.034 ms (0.01%)
ddtrace.internal.runtime 0.292 ms (0.12%)
uuid 0.292 ms (0.12%)
platform 0.258 ms (0.10%)
ddtrace.internal.endpoints 0.070 ms (0.03%)
ddtrace.internal.telemetry.metrics_namespaces 0.070 ms (0.03%)
ddtrace.internal.utils.http 0.066 ms (0.03%)
ddtrace.internal.encoding 0.052 ms (0.02%)
ddtrace.internal._encoding 0.052 ms (0.02%)
ddtrace.internal.settings._telemetry 0.040 ms (0.02%)
ddtrace.internal.periodic 0.040 ms (0.02%)
ddtrace.internal._threads 0.040 ms (0.02%)
ddtrace.internal.telemetry.data 0.024 ms (0.01%)
ddtrace.internal.settings._agent 0.418 ms (0.17%)
urllib.parse 0.252 ms (0.10%)
ipaddress 0.035 ms (0.01%)
socket 0.098 ms (0.04%)
_socket 0.041 ms (0.02%)
ddtrace.internal.settings._core 0.068 ms (0.03%)
ddtrace.internal.native 0.068 ms (0.03%)
ddtrace.internal.native._native 0.068 ms (0.03%)
ddtrace.internal.utils.formats 0.383 ms (0.15%)
ddtrace.internal.compat 0.383 ms (0.15%)
wrapt 0.383 ms (0.15%)
wrapt.importer 0.383 ms (0.15%)
importlib.metadata 0.383 ms (0.15%)
zipfile 0.068 ms (0.03%)
shutil 0.048 ms (0.02%)
zipfile._path 0.021 ms (0.01%)
pathlib 0.042 ms (0.02%)
importlib.metadata._meta 0.032 ms (0.01%)
ddtrace.internal.logger 0.294 ms (0.12%)
dataclasses 0.233 ms (0.09%)
inspect 0.196 ms (0.08%)
dis 0.057 ms (0.02%)
opcode 0.018 ms (0.01%)
_opcode 0.018 ms (0.01%)
ast 0.048 ms (0.02%)
logging 0.026 ms (0.01%)
traceback 0.026 ms (0.01%)
ddtrace.trace 0.844 ms (0.34%)
ddtrace._trace.filters 0.655 ms (0.26%)
ddtrace._trace.processor 0.655 ms (0.26%)
ddtrace.internal.writer 0.399 ms (0.16%)
ddtrace.internal.writer.writer 0.399 ms (0.16%)
gzip 0.244 ms (0.10%)
ddtrace.internal.dogstatsd 0.065 ms (0.03%)
ddtrace.vendor.dogstatsd 0.065 ms (0.03%)
ddtrace.vendor.dogstatsd.base 0.065 ms (0.03%)
ddtrace._trace.sampler 0.155 ms (0.06%)
ddtrace._trace.span 0.155 ms (0.06%)
ddtrace.internal.core 0.070 ms (0.03%)
ddtrace.internal.core.event_hub 0.070 ms (0.03%)
ddtrace._trace._span_pointer 0.054 ms (0.02%)
hashlib 0.054 ms (0.02%)
_hashlib 0.054 ms (0.02%)
ddtrace.internal._rand 0.030 ms (0.01%)
ddtrace.internal.settings.asm 0.056 ms (0.02%)
ddtrace._trace.tracer 0.141 ms (0.06%)
ddtrace.internal.processor.endpoint_call_counter 0.046 ms (0.02%)
ddtrace.internal.debug 0.032 ms (0.01%)
ddtrace._trace.context 0.048 ms (0.02%)
ddtrace._trace._span_link 0.048 ms (0.02%)
ddtrace.internal._unpatched 0.317 ms (0.13%)
subprocess 0.217 ms (0.09%)
contextlib 0.200 ms (0.08%)
fcntl 0.018 ms (0.01%)
json 0.064 ms (0.03%)
json.decoder 0.064 ms (0.03%)
re 0.044 ms (0.02%)
enum 0.044 ms (0.02%)
types 0.044 ms (0.02%)
json.scanner 0.021 ms (0.01%)
_json 0.021 ms (0.01%)
threading 0.036 ms (0.01%)
ddtrace.internal.settings._config 0.100 ms (0.04%)
ddtrace.internal.gitmetadata 0.078 ms (0.03%)
ddtrace.ext.ci 0.078 ms (0.03%)
ddtrace.ext.git 0.043 ms (0.02%)
ddtrace.internal.settings.endpoint_config 0.022 ms (0.01%)
ddtrace._monkey 0.040 ms (0.02%)
ddtrace.vendor.debtcollector 0.022 ms (0.01%)
ddtrace.bootstrap.sitecustomize 4.179 ms (1.67%)
ddtrace.bootstrap.preload 3.370 ms (1.34%)
ddtrace.internal.remoteconfig.client 0.886 ms (0.35%)
ddtrace.internal.settings.profiling 0.395 ms (0.16%)
ddtrace.vendor.psutil 0.266 ms (0.11%)
ddtrace.vendor.psutil._pslinux 0.185 ms (0.07%)
glob 0.033 ms (0.01%)
resource 0.031 ms (0.01%)
ddtrace.internal.datadog.profiling.ddup 0.054 ms (0.02%)
ddtrace.internal.datadog.profiling.ddup._ddup 0.054 ms (0.02%)
multiprocessing 0.363 ms (0.14%)
multiprocessing.context 0.363 ms (0.14%)
multiprocessing.reduction 0.363 ms (0.14%)
pickle 0.363 ms (0.14%)
_pickle 0.295 ms (0.12%)
ddtrace.internal.symbol_db.remoteconfig 0.116 ms (0.05%)
ddtrace.internal.ipc 0.039 ms (0.02%)
ddtrace.internal.core.crashtracking 0.093 ms (0.04%)
ddtrace.debugging._import 0.055 ms (0.02%)
ddtrace.debugging._function.discovery 0.036 ms (0.01%)
ddtrace.internal.settings.dynamic_instrumentation 0.046 ms (0.02%)
ddtrace.internal.settings.symbol_db 0.040 ms (0.02%)
ddtrace.internal.remoteconfig._connectors 0.038 ms (0.02%)
ddtrace.internal.remoteconfig.worker 0.038 ms (0.02%)
ddtrace.internal.products 0.035 ms (0.01%)
ddtrace.internal.runtime.runtime_metrics 0.031 ms (0.01%)
shlex 0.281 ms (0.11%)
ddtrace._trace.trace_handlers 0.266 ms (0.11%)
ddtrace._trace._inferred_proxy 0.118 ms (0.05%)
ddtrace.propagation.http 0.118 ms (0.05%)
ddtrace.internal._tagset 0.039 ms (0.02%)
ddtrace.contrib.trace_utils 0.058 ms (0.02%)
ddtrace.contrib.internal.trace_utils 0.058 ms (0.02%)
ddtrace.contrib.internal.trace_utils_base 0.027 ms (0.01%)
ddtrace.bootstrap.cloning 0.061 ms (0.02%)

@vlad-scherbich vlad-scherbich changed the title Vlad/lockprof asyncio condition feat(profiling): profile asyncio.Condition primitives with Python Lock profiler Dec 8, 2025
@vlad-scherbich vlad-scherbich force-pushed the vlad/lockprof-asyncio-condition branch from 57f1703 to f333100 Compare December 8, 2025 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants