@functools.lru_cache in Python

In Python, lru_cache is a decorator of functools module. It wraps a function with a memoizing callable that saves up to the max size of most recent calls. In other words, it helps in reducing the execution time of the function by using the memoization technique. Thus, it can save time when an expensive or I/O bound function is periodically called with the same arguments.

Syntax

The signature for the lru_cache decorator is as shown below.

@lru_cache(maxsize=128, typed=False)

Here, the maxsize is a parameter that sets the size of a cache. The typed parameter, when set to True, allows the function arguments of different types to be cached separately.

Python @functools.lru_cache Examples:

Example 1: In this case, we are comparing the time to compute the factorial of a number with lru_cache and without lru_cache.

from functools import lru_cache
import time

# Function that computes factorial without lru_cache
def factorial(n):
    if n==1:
        return n
    else:
        return n * factorial(n-1) 
	
# Execution start time
starttime = time.time()
factorial(10)

# Execution end time
endtime = time.time()

print("Time taken to execute Factorial without lru_cache is", endtime-starttime)

# Function that computes Factorial with lru_cache
@lru_cache
def factorial(n):
    if n==1:
        return n
    else:
        return n * factorial(n-1) 
	
starttime = time.time()
factorial(10)

# Execution end time
endtime = time.time()

print("Time taken to execute factorial with lru_cache is", endtime-starttime)
print(factorial.cache_info())

Output

Time taken to execute Factorial without lru_cache is 8.821487426757812e-06
Time taken to execute factorial with lru_cache is 1.0013580322265625e-05
CacheInfo(hits=0, misses=10, maxsize=128, currsize=10)

Example 2: In this case, we are comparing the time to compute the summation of the series of a number with lru_cache and without lru_cache.

from functools import lru_cache
import time
# Function that computes Sum of series without lru_cache
def Sum(n):
    if n==1:
        return n
    else:
        return n + Sum(n-1) 
	
# Execution start time
starttime = time.time()
Sum(10)

# Execution end time
endtime = time.time()

print("Time taken to execute Sum of series without lru_cache is", endtime-starttime)

# Function that computes Sum of series with lru_cache
@lru_cache
def Sum(n):
    if n==1:
        return n
    else:
        return n + Sum(n-1) 
	
starttime = time.time()
Sum(10)

# Execution end time
endtime = time.time()

print("Time taken to execute Sum of series with lru_cache is", endtime-starttime)
print(Sum.cache_info())

Output

Time taken to execute Sum of series without lru_cache is 6.198883056640625e-06
Time taken to execute Sum of series with lru_cache is 1.0013580322265625e-05
CacheInfo(hits=0, misses=10, maxsize=128, currsize=10)

Example 3: In this case, we are comparing the time to compute the factorial of a number with lru_cache and without lru_cache.

from functools import lru_cache
import time

# Function that computes fibonacci without lru_cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2)
	
# Execution start time
starttime = time.time()
fibonacci(10)

# Execution end time
endtime = time.time()

print("Time taken to execute fibonacci without lru_cache is", endtime-starttime)

# Function that computes fibonacci with lru_cache
@lru_cache
def fibonacci(n):
    if n < 2:
        return n
    return fibonacci(n-1) + fibonacci(n-2) 
	
starttime = time.time()
fibonacci(10)

# Execution end time
endtime = time.time()

print("Time taken to execute fibonacci with lru_cache is", endtime-starttime)
print(fibonacci.cache_info())

Output

Time taken to execute fibonacci without lru_cache is 3.457069396972656e-05
Time taken to execute fibonacci with lru_cache is 7.62939453125e-06
CacheInfo(hits=8, misses=11, maxsize=128, currsize=11)

Conclusion

Hence, the use of lru_cache makes the execution faster in a recursive function when same set of code executes.

References

Happy Learning 🙂

Leave A Comment