mirror of
https://github.com/python/cpython.git
synced 2025-12-31 04:23:37 +00:00
gh-138122: Add code examples to the profiling.sampling ddocs (#142609)
This commit is contained in:
parent
3b3838823a
commit
519bee474b
2 changed files with 66 additions and 0 deletions
|
|
@ -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`
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 146 KiB |
Loading…
Add table
Add a link
Reference in a new issue