|
| 1 | +# Profiling in Python: How to Find Performance Bottlenecks |
| 2 | + |
| 3 | +This folder holds sample code that supplements the Real Python tutorial [Profiling in Python: How to Find Performance Bottlenecks](https://realpython.com/python-profiling/). |
| 4 | + |
| 5 | +## Profiler 1: `time` |
| 6 | + |
| 7 | +```shell |
| 8 | +$ python profile_time.py |
| 9 | +sleeper() |
| 10 | + Real time: 1.75 seconds |
| 11 | + CPU time: 0.00 seconds |
| 12 | + |
| 13 | +spinlock() |
| 14 | + Real time: 1.80 seconds |
| 15 | + CPU time: 1.80 seconds |
| 16 | +``` |
| 17 | + |
| 18 | +## Profiler 2: `timeit` |
| 19 | + |
| 20 | +```shell |
| 21 | +$ python profile_timeit.py |
| 22 | +Average time is 0.15 seconds |
| 23 | +``` |
| 24 | + |
| 25 | +## Profiler 3: `cProfile` |
| 26 | + |
| 27 | +```shell |
| 28 | +$ python profile_cprofile.py |
| 29 | +fib(35) = 9227465 |
| 30 | + 29860712 function calls (10 primitive calls) in 9.487 seconds |
| 31 | + |
| 32 | + Ordered by: call count |
| 33 | + |
| 34 | + ncalls tottime percall cumtime percall filename:lineno(function) |
| 35 | +29860703/1 9.487 0.000 9.487 9.487 profile_cprofile.py:5(fib) |
| 36 | + 1 0.000 0.000 0.000 0.000 pstats.py:118(init) |
| 37 | + 1 0.000 0.000 0.000 0.000 pstats.py:137(load_stats) |
| 38 | + 1 0.000 0.000 0.000 0.000 pstats.py:108(__init__) |
| 39 | + 1 0.000 0.000 0.000 0.000 cProfile.py:51(create_stats) |
| 40 | + 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects} |
| 41 | + 1 0.000 0.000 0.000 0.000 {built-in method builtins.hasattr} |
| 42 | + 1 0.000 0.000 0.000 0.000 {built-in method builtins.isinstance} |
| 43 | + 1 0.000 0.000 0.000 0.000 {built-in method builtins.len} |
| 44 | + 1 0.000 0.000 0.000 0.000 {built-in method builtins.print} |
| 45 | +``` |
| 46 | + |
| 47 | +## Profiler 4: `pyinstrument` |
| 48 | + |
| 49 | +Make sure to install the third-party library [`pyinstrument`](https://pypi.org/project/pyinstrument/) from the supplied `requirements.txt` file into a virtual environment first: |
| 50 | + |
| 51 | +```shell |
| 52 | +$ python3 -m venv venv/ |
| 53 | +$ source venv/bin/activate |
| 54 | +(venv) $ python -m pip install -r requirements.txt |
| 55 | +``` |
| 56 | + |
| 57 | +Then, you can run the sample script while you're still in the same virtual environment: |
| 58 | + |
| 59 | +```shell |
| 60 | +(venv) $ python profile_pyinstrument.py |
| 61 | +n = 10 [2.8, 2.8, 2.8, 3.2, 2.4] |
| 62 | +n = 100 [3.04, 3.28, 3.24, 2.92, 3.24] |
| 63 | +n = 1,000 [3.176, 3.192, 3.188, 3.076, 3.132] |
| 64 | +n = 10,000 [3.1376, 3.1328, 3.172, 3.1292, 3.1376] |
| 65 | +n = 100,000 [3.14636, 3.13424, 3.15104, 3.14212, 3.14612] |
| 66 | +n = 1,000,000 [3.141736, 3.141708, 3.14168, 3.141828, 3.140708] |
| 67 | +n = 10,000,000 [3.14143, 3.1403824, 3.1411704, 3.1408808, 3.1420068] |
| 68 | + |
| 69 | + _ ._ __/__ _ _ _ _ _/_ Recorded: 11:49:03 Samples: 243 |
| 70 | + /_//_/// /_\ / //_// / //_'/ // Duration: 24.334 CPU time: 24.298 |
| 71 | +/ _/ v4.5.0 |
| 72 | +
|
| 73 | +Program: profile_pyinstrument.py |
| 74 | +
|
| 75 | +24.300 <module> profile_pyinstrument.py:1 |
| 76 | +└─ 24.300 estimate_pi profile_pyinstrument.py:6 |
| 77 | + ├─ 23.200 <genexpr> profile_pyinstrument.py:7 |
| 78 | + │ ├─ 15.200 point profile_pyinstrument.py:14 |
| 79 | + │ │ ├─ 7.700 Random.uniform random.py:520 |
| 80 | + │ │ │ [4 frames hidden] random, <built-in> |
| 81 | + │ │ │ 6.200 [self] None |
| 82 | + │ │ └─ 7.500 [self] None |
| 83 | + │ ├─ 4.600 [self] None |
| 84 | + │ └─ 3.400 hits profile_pyinstrument.py:10 |
| 85 | + │ ├─ 2.400 [self] None |
| 86 | + │ └─ 1.000 abs None |
| 87 | + │ [2 frames hidden] <built-in> |
| 88 | + └─ 1.100 [self] None |
| 89 | +``` |
| 90 | +
|
| 91 | +## Profiler 5: `perf` |
| 92 | +
|
| 93 | +Make sure to follow the setup instructions in the [Python 3.12 Preview: Support For the Linux perf Profiler](https://realpython.com/python312-perf-profiler/) tutorial. |
| 94 | +
|
| 95 | +Next, record samples into a local binary file named `perf.data`: |
| 96 | +
|
| 97 | +```shell |
| 98 | +$ sudo perf record -g -F 999 $HOME/python-custom-build/bin/python3 -X perf profile_perf.py |
| 99 | +``` |
| 100 | +
|
| 101 | +Finally, display a report by issuing the following command while you're in the same folder: |
| 102 | + |
| 103 | +```shell |
| 104 | +$ sudo perf report |
| 105 | +``` |
| 106 | + |
| 107 | +For an alternative view, try this instead: |
| 108 | + |
| 109 | +```shell |
| 110 | +$ sudo perf report --hierarchy --sort comm,dso,sample |
| 111 | +``` |
0 commit comments