Have a look at timeit, the python profiler and pycallgraph. Also make sure to have a look at the comment below by nikicc mentioning "SnakeViz". It gives you yet another visualisation of profiling data which can be helpful.

timeit

def test():
    """Stupid test function"""
    lst = []
    for i in range(100):
        lst.append(i)

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test()", setup="from __main__ import test"))

    # For Python>=3.5 one can also write:
    print(timeit.timeit("test()", globals=locals()))

Essentially, you can pass it python code as a string parameter, and it will run in the specified amount of times and prints the execution time. The important bits from the docs:

timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None) Create a Timer instance with the given statement, setup code and timer function and run its timeit method with number executions. The optional globals argument specifies a namespace in which to execute the code.

... and:

Timer.timeit(number=1000000) Time number executions of the main statement. This executes the setup statement once, and then returns the time it takes to execute the main statement a number of times, measured in seconds as a float. The argument is the number of times through the loop, defaulting to one million. The main statement, the setup statement and the timer function to be used are passed to the constructor.

Note: By default, timeit temporarily turns off garbage collection during the timing. The advantage of this approach is that it makes independent timings more comparable. This disadvantage is that GC may be an important component of the performance of the function being measured. If so, GC can be re-enabled as the first statement in the setup string. For example:

timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()

Profiling

Profiling will give you a much more detailed idea about what's going on. Here's the "instant example" from the official docs:

import cProfile
import re
cProfile.run('re.compile("foo|bar")')

Which will give you:

      197 function calls (192 primitive calls) in 0.002 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
     1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)

Both of these modules should give you an idea about where to look for bottlenecks.

Also, to get to grips with the output of profile, have a look at this post

pycallgraph

NOTE pycallgraph has been officially abandoned since Feb. 2018. As of Dec. 2020 it was still working on Python 3.6 though. As long as there are no core changes in how python exposes the profiling API it should remain a helpful tool though.

This module uses graphviz to create callgraphs like the following:

You can easily see which paths used up the most time by colour. You can either create them using the pycallgraph API, or using a packaged script:

pycallgraph graphviz -- ./mypythonscript.py

The overhead is quite considerable though. So for already long-running processes, creating the graph can take some time.

Answer from exhuma on Stack Overflow
๐ŸŒ
GitHub
github.com โ€บ python โ€บ pyperformance
GitHub - python/pyperformance: Python Performance Benchmark Suite ยท GitHub
The pyperformance project is intended to be an authoritative source of benchmarks for all Python implementations. The focus is on real-world benchmarks, rather than synthetic benchmarks, using whole applications when possible.
Starred by 1K users
Forked by 202 users
Languages ย  Python 84.0% | HTML 14.4% | Shell 1.6%
๐ŸŒ
Readthedocs
pyperformance.readthedocs.io
The Python Performance Benchmark Suite โ€” Python Performance Benchmark Suite 1.14.0 documentation
The pyperformance project is intended to be an authoritative source of benchmarks for all Python implementations.
๐ŸŒ
Medium
medium.com โ€บ @hasanshahjahan โ€บ benchmarking-and-profiling-in-python-dd4db60e3149
Benchmarking and Profiling in Python | by Miah Md Shahjahan | Medium
October 11, 2025 - Benchmarking is the process of measuring the performance of code under controlled conditions. It measures execution time, memory, or throughput to compare implementations. A simple and accurate timing to measure execution time.
๐ŸŒ
Switowski
switowski.com โ€บ blog โ€บ how-to-benchmark-python-code
How to Benchmark (Python) Code - Sebastian Witowski
November 17, 2022 - The easiest way to measure how long it takes to run some code is to use the timeit module. You can write python -m timeit your_code(), and Python will print out how long it took to run whatever your_code() does.
๐ŸŒ
Python
speed.python.org
Python Speed Center
Track performance changes in the latest revisions ยท Analyze performance over time ยท Compare different executables and revisions ยท
๐ŸŒ
Readthedocs
pyperformance.readthedocs.io โ€บ benchmarks.html
Benchmarks โ€” Python Performance Benchmark Suite 1.14.0 documentation
Run the 2to3 tool on the pyperformance/benchmarks/data/2to3/ directory: copy of the django/core/*.py files of Django 1.1.4, 9 files. Run the python -m lib2to3 -f all <files> command where python is sys.executable. So the test does not only mesure the performance of Python itself, but also the ...
๐ŸŒ
PyPI
pypi.org โ€บ project โ€บ pytest-benchmark
pytest-benchmark ยท PyPI
A ``pytest`` fixture for benchmarking code. It will group the tests into rounds that are calibrated to the chosen timer.
      ยป pip install pytest-benchmark
    
Published ย  Nov 09, 2025
Version ย  5.2.3
Find elsewhere
Top answer
1 of 15
164

Have a look at timeit, the python profiler and pycallgraph. Also make sure to have a look at the comment below by nikicc mentioning "SnakeViz". It gives you yet another visualisation of profiling data which can be helpful.

timeit

def test():
    """Stupid test function"""
    lst = []
    for i in range(100):
        lst.append(i)

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test()", setup="from __main__ import test"))

    # For Python>=3.5 one can also write:
    print(timeit.timeit("test()", globals=locals()))

Essentially, you can pass it python code as a string parameter, and it will run in the specified amount of times and prints the execution time. The important bits from the docs:

timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000, globals=None) Create a Timer instance with the given statement, setup code and timer function and run its timeit method with number executions. The optional globals argument specifies a namespace in which to execute the code.

... and:

Timer.timeit(number=1000000) Time number executions of the main statement. This executes the setup statement once, and then returns the time it takes to execute the main statement a number of times, measured in seconds as a float. The argument is the number of times through the loop, defaulting to one million. The main statement, the setup statement and the timer function to be used are passed to the constructor.

Note: By default, timeit temporarily turns off garbage collection during the timing. The advantage of this approach is that it makes independent timings more comparable. This disadvantage is that GC may be an important component of the performance of the function being measured. If so, GC can be re-enabled as the first statement in the setup string. For example:

timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()

Profiling

Profiling will give you a much more detailed idea about what's going on. Here's the "instant example" from the official docs:

import cProfile
import re
cProfile.run('re.compile("foo|bar")')

Which will give you:

      197 function calls (192 primitive calls) in 0.002 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
     1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)

Both of these modules should give you an idea about where to look for bottlenecks.

Also, to get to grips with the output of profile, have a look at this post

pycallgraph

NOTE pycallgraph has been officially abandoned since Feb. 2018. As of Dec. 2020 it was still working on Python 3.6 though. As long as there are no core changes in how python exposes the profiling API it should remain a helpful tool though.

This module uses graphviz to create callgraphs like the following:

You can easily see which paths used up the most time by colour. You can either create them using the pycallgraph API, or using a packaged script:

pycallgraph graphviz -- ./mypythonscript.py

The overhead is quite considerable though. So for already long-running processes, creating the graph can take some time.

2 of 15
47

I use a simple decorator to time the func

import time

def st_time(func):
    """
        st decorator to calculate the total time of a func
    """

    def st_func(*args, **keyArgs):
        t1 = time.time()
        r = func(*args, **keyArgs)
        t2 = time.time()
        print("Function=%s, Time=%s" % (func.__name__, t2 - t1))
        return r

    return st_func
๐ŸŒ
Reddit
reddit.com โ€บ r/python โ€บ how to benchmark your python code
r/Python on Reddit: How to Benchmark your Python Code
November 17, 2025 -

Hi!

https://codspeed.io/docs/guides/how-to-benchmark-python-code

I just wrote a guide on how to test the performance of your Python code with benchmarks. It 's a good place to start if you never did it!

Happy to answer any question!

๐ŸŒ
CodSpeed Docs
codspeed.io โ€บ docs โ€บ guides โ€บ how-to-benchmark-python-code
How to Benchmark Python Code? - CodSpeed Docs
This gives you accurate performance data without the noise of test setup. Letโ€™s run this benchmark by filtering the pytest command to just this file: uv run pytest tests/test_outlier_detection.py --codspeed ... =============================== test session starts =============================== platform darwin -- Python 3.13.3, pytest-8.4.2, pluggy-1.6.0 codspeed: 4.2.0 (enabled, mode: walltime, callgraph: not supported, timer_resolution: 41.7ns) CodSpeed had to disable the following plugins: pytest-benchmark benchmark: 5.2.1 (defaults: timer=time.perf_counter disable_gc=False min_rounds=5 min_time=0.000005 max_time=1.0 calibration_precision=10 warmup=False warmup_iterations=100000) rootdir: /Users/user/projects/CodSpeedHQ/docs-guides/python configfile: pyproject.toml plugins: benchmark-5.2.1, codspeed-4.2.0 collected 6 items tests/test_outlier_detection.py ......
๐ŸŒ
Miguel Grinberg
blog.miguelgrinberg.com โ€บ post โ€บ python-3-14-is-here-how-fast-is-it
Python 3.14 Is Here. How Fast Is It? - miguelgrinberg.com
In Python 3.13 the free-threading interpreter ran about 2.2x faster than the standard interpreter. In 3.14 the performance improvement is about 3.1x. This is an exciting result! To complete this benchmarking exercise, below you can see the results ...
๐ŸŒ
GitHub
github.com โ€บ dionhaefner โ€บ pyhpc-benchmarks
GitHub - dionhaefner/pyhpc-benchmarks: A suite of benchmarks for CPU and GPU performance of the most popular high-performance libraries for Python :rocket:
This is a suite of benchmarks to test the sequential CPU and GPU performance of various computational backends with Python frontends.
Starred by 333 users
Forked by 26 users
Languages ย  Python 96.6% | Jupyter Notebook 2.7% | Shell 0.7% | Python 96.6% | Jupyter Notebook 2.7% | Shell 0.7%
๐ŸŒ
Bencher
bencher.dev โ€บ learn โ€บ benchmarking โ€บ python โ€บ pytest-benchmark
How to benchmark Python code with pytest-benchmark | Bencher - Continuous Benchmarking
November 3, 2024 - It allows developers to measure and compare the performance of their code by running benchmarks alongside their unit tests. Users can easily compare their benchmark results locally and export their results in various formats, such as JSON. airspeed velocity (asv) is another advanced benchmarking tool in the Python ecosystem.
๐ŸŒ
Perfpy
perfpy.com
perfpy: Benchmark Python Snippets Online
We cannot provide a description for this page right now
๐ŸŒ
Readthedocs
pyperformance.readthedocs.io โ€บ usage.html
Usage โ€” Python Performance Benchmark Suite 1.14.0 documentation
A benchmark is always written for ... and so have a different meaning. The pyperformance benchmark suite has multiple goals: Help to detect performance regression in a Python implementation...
๐ŸŒ
GitHub
github.com โ€บ faster-cpython โ€บ benchmarking-public
GitHub - faster-cpython/benchmarking-public: A public mirror of our benchmarking runner repository ยท GitHub
To collect Linux perf sampling profile data for a benchmarking run, run the _benchmark action and check the perf checkbox. The results will be available as "artifacts" on the run page after the run -- they are not committed directly to the repository. The python -m bench_runner profiling_plot command can be used to turn the raw perf results into tables and graphs.
Starred by 125 users
Forked by 11 users
Languages ย  Python
๐ŸŒ
Xn--mxac
xn--mxac.net โ€บ python-performance-benchmark-tool.html
Python Performance Benchmark Tool - ฮฑฮฒ.net
Python Performance Benchmark Tool: Benchmark and optimize your Python code performance across different versions. Analyze execution speed of classic algorithms and improve code efficiency with this cross-platform Python tool.
๐ŸŒ
GitHub
github.com โ€บ vstinner โ€บ pyperformance_results
GitHub - vstinner/pyperformance_results: Results of the Python performance benchmark suite
Results of the Python performance benchmark suite computed on the speed-python server: compressed perf JSON files.
Author ย  vstinner
๐ŸŒ
Miguel Grinberg
blog.miguelgrinberg.com โ€บ post โ€บ is-python-really-that-slow
Is Python Really That Slow? - miguelgrinberg.com
But as I said above, I was only trying to form an idea of the performance differences between Python versions, and this is enough to satisfy my curiosity. Except for one last question. My final effort was to move all the files to my Mac laptop to re-run all the tests and see if the results match. The reason this is significant is because Mac computers these days run on ARM based CPUs, so performance optimizations may have completely different characteristics than those designed for Intel chips. Here is a chart of the Fibonacci benchmark results including the Intel (blue bars) and M2 (red bars) results.