From: Pablo Galindo Salgado Date: Fri, 12 Dec 2025 01:37:47 +0000 (+0000) Subject: gh-138122: Add code examples to the profiling.sampling ddocs (#142609) X-Git-Tag: v3.15.0a3~90 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=519bee474b63f5c8019e9104ed819911c6e650f8;p=thirdparty%2FPython%2Fcpython.git gh-138122: Add code examples to the profiling.sampling ddocs (#142609) --- diff --git a/Doc/library/profiling.sampling.rst b/Doc/library/profiling.sampling.rst index 2bad2a8d1ab3..a05adf8c3da2 100644 --- a/Doc/library/profiling.sampling.rst +++ b/Doc/library/profiling.sampling.rst @@ -191,6 +191,11 @@ production systems. The target process requires no modification and need not be restarted. The profiler attaches, collects samples for the specified duration, then detaches and produces output. +:: + + python -m profiling.sampling attach --live 12345 + python -m profiling.sampling attach --flamegraph -d 30 -o profile.html 12345 + On most systems, attaching to another process requires appropriate permissions. See :ref:`profiling-permissions` for platform-specific requirements. @@ -529,6 +534,25 @@ I/O-bound or waiting. The function spends most of its time waiting for network, disk, locks, or sleep. CPU optimization won't help here; consider async I/O, connection pooling, or reducing wait time instead. +.. code-block:: python + + import time + + def do_sleep(): + time.sleep(2) + + def do_compute(): + sum(i**2 for i in range(1000000)) + + if __name__ == "__main__": + do_sleep() + do_compute() + +:: + + python -m profiling.sampling run --mode=wall script.py # do_sleep ~98%, do_compute ~1% + python -m profiling.sampling run --mode=cpu script.py # do_sleep absent, do_compute dominates + GIL mode -------- @@ -553,6 +577,29 @@ GIL?" and "why are my other threads starving?" It can also be useful in single-threaded programs to distinguish Python execution time from time spent in C extensions or I/O. +.. code-block:: python + + import hashlib + + def hash_work(): + # C extension - releases GIL during computation + for _ in range(200): + hashlib.sha256(b"data" * 250000).hexdigest() + + def python_work(): + # Pure Python - holds GIL during computation + for _ in range(3): + sum(i**2 for i in range(1000000)) + + if __name__ == "__main__": + hash_work() + python_work() + +:: + + python -m profiling.sampling run --mode=cpu script.py # hash_work ~42%, python_work ~38% + python -m profiling.sampling run --mode=gil script.py # hash_work ~5%, python_work ~60% + Exception mode -------------- @@ -952,6 +999,25 @@ stack often shows event loop internals rather than the logical flow of your coroutines. Async-aware mode addresses this by tracking which task is running and presenting stacks that reflect the ``await`` chain. +.. code-block:: python + + import asyncio + + async def fetch(url): + await asyncio.sleep(0.1) + return url + + async def main(): + for _ in range(50): + await asyncio.gather(fetch("a"), fetch("b"), fetch("c")) + + if __name__ == "__main__": + asyncio.run(main()) + +:: + + python -m profiling.sampling run --async-aware --flamegraph -o out.html script.py + .. note:: Async-aware profiling requires the target process to have the :mod:`asyncio` diff --git a/Lib/profiling/sampling/_assets/tachyon-logo.png b/Lib/profiling/sampling/_assets/tachyon-logo.png index fddeaafe7e09..f87e006b14f2 100644 Binary files a/Lib/profiling/sampling/_assets/tachyon-logo.png and b/Lib/profiling/sampling/_assets/tachyon-logo.png differ