Timing Function in Python: A Guide

You can time Python functions to measure how long it takes for your Python code to run or evaluate the performance of different approaches using time.perf)counter(), time.time() and more. Here’s how.

Written by Benedict Neo
Published on Jun. 05, 2024
Person holding a timer representing timing functions in Python
Image: Shutterstock / Built In
Brand Studio Logo

Have you ever wondered how long it takes for your Python code to run? Or have you wanted to compare the performance of different approaches to solving a problem?

If so, you’ll need to know how to time your Python functions.

You can time Python functions using the time module, the timeit module and profiling tools.

4 Common Ways to Time a Function in Python

  1. Time.perf_counter()
  2. Time.time()
  3. Timeit module
  4. Cprofile and profile

By the end of this guide, you’ll have a good understanding of how to measure the elapsed time of your Python code, and you’ll be able to use the appropriate method for your specific needs.

 

4 Methods to Timing Functions in Python

There are four common methods to time a function in Python, including: time.perf_counter(), time.time(), timeit and cprofile or profile. Let’s look at each one.

1. Time.perf_counter()

The time.perf_counter() function is a high-resolution timing function that uses the processor’s performance counter to measure time.

It’s suitable for measuring the time taken by a function and the time taken by small code blocks or individual statements.

To use this function, you can call time.perf_counter() before and after the code you want to time, subtracting the start time from the end time to get the elapsed time.

One advantage of perf_counter() is that it’s based on a monotonic clock, which always increments and never goes backward. This makes it more suitable for measuring the elapsed time of a process or event.

2. Time.time()

The time.time() function returns the current time in seconds since the epoch. The epoch is a predefined point in time, usually the beginning of the year 1970.

It’s not as precise as perf_counter(), but it can be useful for timing longer-running functions or scripts.

One potential disadvantage of time() is that it’s based on the system clock, which can be adjusted by the user or the system administrator, so the clock can go backward if the system time is changed.

A tutorial on how to time a function in Python with time.time(). | Video: Python Martón

3. Timeit Module

The timeit module provides a simple way to time the execution of small bits of Python code.

It can be used to time a single function by wrapping it in a timeit.Timer object and calling the timeit() method.

One advantage of the timeit module is that it allows you to specify the number of times the function should be run, which can help return more accurate timing results.

4. Profiling Tools

If you want to get more detailed information about the performance of your code, you can use a profiling tool such as cProfile or profile.

These tools can provide detailed statistics about the time taken by different parts of your code, the number of function calls and the amount of memory used.

Profiling tools can be particularly useful for identifying bottlenecks in your code and optimizing the performance of your application.

There are still many other ways to time functions, using datetime.datetime.now(), time.clock(), time.process_time(), etc, but we’ll focus on the above four for now.

More on PythonPython Tree Implementation: A Guide

 

Timing Functions in Python With Example Code

Let’s test the methods on the following function.

def fibonacci(n):
    """Calculate the nth Fibonacci number using recursion."""
    if n <= 0:
        return 0
    elif n == 1:
        return 1
    else:
        return fibonacci(n - 1) + fibonacci(n - 2)

1. perf_counter()

import time

start = time.perf_counter()
result = fibonacci(20)
end = time.perf_counter()
elapsed = end - start
print(f'Time taken: {elapsed:.6f} seconds')

Time taken: 0.002537 seconds

2. time.time()

import time

start = time.time()
result = fibonacci(20)
end = time.time()
elapsed = end - start
print(f'Time taken: {elapsed:.6f} seconds')

Time taken: 0.002808 seconds

3. Timeit

import timeit

timer = timeit.Timer(lambda: fibonacci(20))
elapsed = timer.timeit(1)
print(f'Time taken: {elapsed:.6f} seconds')

Time taken: 0.002818 seconds

4. Cprofile

import cProfile

cProfile.run('fibonacci(20)')
         21894 function calls (4 primitive calls) in 0.005 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
  21891/1    0.005    0.000    0.005    0.005 4282974425.py:1(fibonacci)
        1    0.000    0.000    0.005    0.005 <string>:1(<module>)
        1    0.000    0.000    0.005    0.005 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Based on the output, ncalls tells us the function was called 21,891 times, the total time spent was 0.005, and the average time spent per call was 0.000 seconds.

Now that you’ve seen the code samples, you’re probably wondering which method should you use?

 

Best Method to Time a Function in Python

When you’re deciding which method to use to time a function in Python, it’s important to consider the code and what you want to measure. Let’s take a look at when to use each of the methods. 

Perf_counter() vs. Time()

Let’s reiterate the differences between perf_counter() and time().

  • time.perf_counter() uses the processor’s performance counter to measure time, while time.time() uses the system clock. In general, perf_counter() is more precise and has a higher resolution than time(), so it’s often the better choice for timing small code blocks or individual statements.
  • time.perf_counter() is based on a monotonic clock, which means that it always increments and never goes backward. This makes it more suitable for measuring the elapsed time of a process or event. On the other hand, time.time() is based on the system clock, which can be adjusted by the user or the system administrator. So, the clock can go back if the system time is changed.

If you want to measure the elapsed time of a process or event and you need high precision and a monotonic clock, time.perf_counter() is the best choice.

On the other hand, if you need to measure the elapsed time of a longer-running script or function, and precision is not as important, time.time() may be sufficient.

Use Timeit for Small Bits of Code

You might use the timeit module when you want to quickly and easily time the execution of small bits of Python code. It’s particularly useful when you want to compare the performance of different approaches to solving a problem or when you want to optimize a specific piece of code.

Use Profile for Performance

You might use profiling tools when you want to get a detailed understanding of the performance of your code. Profiling tools can provide information about the time taken by different parts of your code, the number of function calls and the amount of memory used. This can help identify bottlenecks and optimize your code.

For example, suppose you have a large Python script that is running slowly, and you want to find out which parts of the code are taking the most time.

The output of cProfile will show you a breakdown of the time taken by each function in your script, as well as the number of times each function was called. You can use this information to identify which functions take the most time and focus your optimization efforts on those functions.

More on Python4 Ways to Insert a Python Variable in a String

 

Decorator to Time Functions Explained

To quickly time functions that you write, you can write a decorator that uses the perf_counter() function.

Then for any function you define, you just have to include the @timeit and it will show how long it took to run that function.

Below, the timeit decorator is defined, and is added to the calculate_pi function.

The calculate_pi function approximates the value of pi using the Monte Carlo method. It generates n random points in a unit square and counts the number of points that fall inside the unit circle inscribed within the square. The value of pi is then calculated as the ratio of the number of points inside the circle to the total number of points, multiplied by four.

import time
import random

def timeit(func):
    def wrapper(*args, **kwargs):
        start = time.perf_counter()
        result = func(*args, **kwargs)
        end = time.perf_counter()
        elapsed = end - start
        print(f'Time taken: {elapsed:.6f} seconds')
        return result
    return wrapper

@timeit
def calculate_pi(n):
    """Calculate and return an approximation of pi using the Monte Carlo method."""
    inside = 0
    for i in range(n):
        x = random.uniform(-1, 1)
        y = random.uniform(-1, 1)
        if x ** 2 + y ** 2 <= 1:
            inside += 1
    pi = (inside / n) * 4
    return pi

pi = calculate_pi(1000000)

Time taken: 0.705406 seconds

At the bottom, when we call calculate_pi, it shows us it took 0.7 seconds to run.

Timing Python functions is a useful skill to have in your toolkit as a developer.

Whether you’re optimizing code for performance or simply want to understand how long it takes for your code to run, several different methods are available to help you measure the elapsed time of your Python functions.

We’ve covered four of the most common methods in this guide: using the time module, the timeit module and profiling tools. Now, it’s your turn to put this knowledge into practice.

Try timing some Python functions using the different methods we’ve discussed, and see how they compare.

Frequently Asked Questions

If you want to measure how long it takes for your code to run or compare the performance of different code approaches, there are four common approaches you can take in Python, including: 

  1. time.perf_counter()
  2. time.time()
  3. Timeit 
  4. CProfile or profile

The best method for timing a function in Python depends on your task.

  1. Time.perf_counter() is based on a monotonic clock, which means that it always increments and never goes backward. It’s best for measuring the elapsed time of a process.
  2. Time.time() uses a system clock, which makes it more useful for measuring small blocks of code.
  3. Timeit can quickly return the time it takes for small blocks of code to run, making it useful for comparing different approaches.
  4. CProflie() returns detailed analysis of how much time each function takes to process in your code, which makes it best for code optimization tasks. 
Explore Job Matches.