Scalene: a high-performance, high-precision CPU and memory profiler for Python
Sadly, relying on Python&#x27;s signal handling is not enough to get robust profiling information the moment your code is spending a significant chunk of time outside of simple Python calls. This is because signals don&#x27;t get delivered to the Python level until the interpreter comes back from C land, and it&#x27;s possible to get stuck in C land even with pure Python code.<p>To wit:<p><pre><code>  $ python -m scalene trace.py
  f1 1.3852 312499987500000
  f2 1.2420 2812499962500000
  f3 1.5018 1.5
  trace.py: % of CPU time =  33.66% out of   4.13s.
  Line  | CPU %    |  [trace.py]
     1  |          | #!&#x2F;usr&#x2F;bin&#x2F;env python
     2  |          | 
     3  |          | import time
     4  |          | 
     5  |          | def timed(f):
     6  |          |     def f_timed(*args, **kwargs):
     7  |          |         t = time.time()
     8  |          |         r = f(*args, **kwargs)
     9  |          |         t = time.time() - t
    10  |          |         print(&#x27;%s %.4f %s&#x27; % (f.__name__, t, r))
    11  |          |     return f_timed
    12  |          | 
    13  |          | @timed
    14  |          | def f1(n):
    15  |          |     s = 0
    16  |  17.99%  |     for i in range(n):
    17  |  81.29%  |         s += i
    18  |          |     return s
    19  |          | 
    20  |          | @timed
    21  |          | def f2(n):
    22  |   0.72%  |     return sum(range(n))
    23  |          | 
    24  |          | @timed
    25  |          | def f3(t):
    26  |          |     time.sleep(t)
    27  |          |     return t
    28  |          | 
    29  |          | if __name__ == &#x27;__main__&#x27;:
    30  |          |     f1(25_000_000)
    31  |          |     f2(75_000_000)
    32  |          |     f3(1.5)</code></pre>