Python profiler using USDT probes for low-overhead performance monitoring with bpftrace
Project description
🐍 pyusdt 🐝
A Python profiler using USDT (User-level Statically Defined Tracing) probes for low-overhead performance monitoring.
Overview
pyusdt instruments Python code execution with USDT probes that can be traced using bpftrace. It uses Python's sys.monitoring API for efficient function-level tracing.
This tool is particularly designed to enable bpftrace workflows where traces need to span both kernel and userspace, allowing you to correlate Python function calls with kernel events in a single trace session.
Zero-overhead when not traced: pyusdt uses dynamic callback registration combined with USDT semaphores. When no tracer is attached, monitoring callbacks are not registered with sys.monitoring, resulting in essentially zero performance impact on your Python code. When bpftrace or another tracer attaches, callbacks are automatically enabled within ~100ms.
Requirements
- Python 3.12+ (for
sys.monitoringAPI) - Linux with USDT support
- bpftrace
Building
Make sure gcc and Python development headers are installed. Compile the USDT probe extension:
make
This creates libpyusdt.so, a Python C extension module with embedded USDT probes.
Usage
Run any Python script with USDT monitoring:
python -m pyusdt <script.py> [args...]
Example:
python -m pyusdt sleep.py
Configuration
Adjust the polling interval for tracer detection (default: 100ms):
# Check for attached tracers every 50ms
PYUSDT_CHECK_MSEC=50 python -m pyusdt sleep.py
# Check every 500ms (lower overhead, slower tracer detection)
PYUSDT_CHECK_MSEC=500 python -m pyusdt sleep.py
Tracing with bpftrace
Use the included bpftrace script to trace function calls:
sudo bpftrace sample.bt -c "python -m pyusdt sleep.py"
Or attach to a running process:
# In terminal 1:
python -m pyusdt sleep.py
# In terminal 2:
sudo bpftrace sample.bt -p $(pgrep -f "python -m pyusdt")
Testing
Run the test suite:
make test
How it Works
libpyusdt.so- Python C extension module with USDT probe definitions andsys.monitoringintegrationpyusdt/__init__.py- Minimal Python wrapper that imports the C extensionpyusdt/__main__.py- Entry point forpython -m pyusdtexecutionsample.bt- bpftrace script to display traced function callsusdt.h- Header-only USDT library from libbpf/usdt
When the pyusdt module is imported, the C extension starts a background thread that polls USDT semaphores to detect when a tracer (like bpftrace) attaches. Only when a tracer is active does pyusdt register callbacks with Python's sys.monitoring API (see PEP 669). When the tracer detaches, callbacks are automatically unregistered.
The following monitoring events are captured and exposed as USDT probes when tracing is active:
- PY_START - Function entry
- PY_RESUME - Generator/coroutine resumption
- PY_RETURN - Function return with return value
- PY_YIELD - Generator yield with yielded value
- CALL - Function calls
- LINE - Line-by-line execution
Each event triggers its corresponding USDT probe with relevant context (function name, filename, line number, and event-specific data).
Zero-Overhead Design
pyusdt achieves true zero overhead when not being traced through:
- USDT Semaphores: The libbpf/usdt library uses kernel-managed semaphores that are incremented when tracers attach
- Dynamic Callback Registration: A background thread polls semaphores every 100ms and only registers
sys.monitoringcallbacks when needed - Automatic Enable/Disable: When bpftrace attaches, monitoring activates within ~100ms; when it detaches, monitoring stops immediately
This means you can leave pyusdt enabled in production with virtually no performance impact until you need to trace.
References
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyusdt-0.1.0.tar.gz.
File metadata
- Download URL: pyusdt-0.1.0.tar.gz
- Upload date:
- Size: 24.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1bad5503fbb563f5a26c3d1becb19464f6c430582ae6aa9d982bd1ef06aa104a
|
|
| MD5 |
9bcdc1205747c1ecb90a490e3b8f9903
|
|
| BLAKE2b-256 |
b7ec92d10b973a2a74fb93da26da81fe4d24ddb92a2452f6d8af9de8da042ddb
|
Provenance
The following attestation bundles were made for pyusdt-0.1.0.tar.gz:
Publisher:
release.yml on natoscott/pyusdt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyusdt-0.1.0.tar.gz -
Subject digest:
1bad5503fbb563f5a26c3d1becb19464f6c430582ae6aa9d982bd1ef06aa104a - Sigstore transparency entry: 622605326
- Sigstore integration time:
-
Permalink:
natoscott/pyusdt@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/natoscott
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyusdt-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyusdt-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 29.9 kB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3bb2ee910dd38ef6320c21ae54cb39b880775a8fdb1c7c3a680a69fd570056df
|
|
| MD5 |
b96e2cf522b3199589941d66cfa07e59
|
|
| BLAKE2b-256 |
b9764acd7505efffe4ce12737cf855841d8550faaf23e610798385fa2c66fceb
|
Provenance
The following attestation bundles were made for pyusdt-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on natoscott/pyusdt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyusdt-0.1.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
3bb2ee910dd38ef6320c21ae54cb39b880775a8fdb1c7c3a680a69fd570056df - Sigstore transparency entry: 622605329
- Sigstore integration time:
-
Permalink:
natoscott/pyusdt@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/natoscott
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyusdt-0.1.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyusdt-0.1.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 29.0 kB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9bc29f6c094def4619106b2bd9dac2aeb895b20878ea97e5d37817fa485c9d12
|
|
| MD5 |
d28193ffc9433d924e85187f5ef8902f
|
|
| BLAKE2b-256 |
8dd7bae2805c19261540b75504d96821acd51da29b2b00d004f7f738f4f43870
|
Provenance
The following attestation bundles were made for pyusdt-0.1.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on natoscott/pyusdt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyusdt-0.1.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
9bc29f6c094def4619106b2bd9dac2aeb895b20878ea97e5d37817fa485c9d12 - Sigstore transparency entry: 622605332
- Sigstore integration time:
-
Permalink:
natoscott/pyusdt@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/natoscott
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyusdt-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyusdt-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 29.9 kB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c6265a45e2841569f86437955a944a59d7699ca4597b00c207b2bc45e2052053
|
|
| MD5 |
c062c39bfaa1b153c3dde9037a8cfd78
|
|
| BLAKE2b-256 |
ef90f5354134a08d7b04b98dc1988db2f2caffb2166eb0a8d32a9d1e22df1ff7
|
Provenance
The following attestation bundles were made for pyusdt-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on natoscott/pyusdt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyusdt-0.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
c6265a45e2841569f86437955a944a59d7699ca4597b00c207b2bc45e2052053 - Sigstore transparency entry: 622605330
- Sigstore integration time:
-
Permalink:
natoscott/pyusdt@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/natoscott
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Trigger Event:
release
-
Statement type:
File details
Details for the file pyusdt-0.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyusdt-0.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 29.1 kB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64, manylinux: glibc 2.5+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a10b4b624890d2400007ae224bad96ac72952d8a0be01f36cf34e4f4c67a4694
|
|
| MD5 |
d15f1e5bc70e13949f9d8a9495427aaf
|
|
| BLAKE2b-256 |
09a1ec8c109b5277eec0f4d33e5159096c244fe55c5847c4e19e513f7175bc72
|
Provenance
The following attestation bundles were made for pyusdt-0.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on natoscott/pyusdt
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyusdt-0.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
a10b4b624890d2400007ae224bad96ac72952d8a0be01f36cf34e4f4c67a4694 - Sigstore transparency entry: 622605337
- Sigstore integration time:
-
Permalink:
natoscott/pyusdt@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/natoscott
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@a80db0fbb079feed24a5f3c8902af910a3e55834 -
Trigger Event:
release
-
Statement type: