.. role:: python(code) :language: python .. index:: profiling profiling; deterministic profiling; probabilistic Cpu profiling ------------- There are two complementary objectives: + get a big picture of where the time is spent :python:`cProfile, pstats` (standard) or :python:`pyinstrument` (external dependency). For comments on `deterministic `_ vs `statistical `_ profiling. + monitor the performance of the most important functions (potentially as a function of the input size) with :python:`timeit`. The goal can be to confirm a potential theoretical complexity analysis. During an optimization phase, it is mandatory to choose between different solutions based on empirical evidence. .. code-block:: python :linenos: from collections.abc import Callable import cProfile import io from pathlib import Path import pstats import time from timeit import timeit import pyinstrument .. literalinclude:: ../../../../src/tools_methods/profiling/cpu.py :pyobject: profile :name: profile :linenos: :caption: src .. literalinclude:: ../../../../src/tools_methods/profiling/cpu.py :pyobject: example :name: example :linenos: :caption: src The built-in package ``cProfile`` gives: .. code-block:: console Ordered by: internal time Function called... ncalls tottime cumtime {built-in method time.sleep} -> test_cpu.py:24(do_something) -> 1 0.000 0.010 test_cpu.py:18(single) 3 0.000 0.030 test_cpu.py:21(repeated) test_cpu.py:21(repeated) -> 3 0.030 0.030 {built-in method time.sleep} test_cpu.py:18(single) -> 1 0.010 0.010 {built-in method time.sleep} {method 'disable' of '_lsprof.Profiler' objects} -> which corresponds to the call graph: .. _`fig:call_graph`: .. figure:: call_graph.png :width: 300 :alt: Call graph Call graph the package :python:`pyinstrument` returns: .. code-block:: console 0.040 example cpu.py:31 └─ 0.040 do_something cpu.py:44 ├─ 0.030 repeated cpu.py:41 │ └─ 0.030 sleep └─ 0.010 single cpu.py:38 └─ 0.010 sleep