Speed up Python functions with memoization and lru_cache

Python trades runtime speed for programmer convenience, and most of the time it’s a good tradeoff. One doesn’t typically need the raw speed of C for most workaday applications. And when you need to squeeze more performance out of Python, you don’t always have to turn to C; there’s plenty within Python itself to aid with that.

One performance-enhancement technique common to many languages, and one Python can use too, is memoization—caching the results of a function call so that future calls with the same inputs don’t have to be recomputed from scratch. Python provides a standard library utility, lru_cache, to do this.

Memoization basics

Here’s a simple example of a function that’s a good use case for memoization:

from math import sin

def sin_half(x):
    return sin(x)/2

A function like this has two qualities that make it worth memoizing:

  1. The output of the function is deterministic. Whenever you provide a certain input, you get the same output every time. Functions that rely on something outside the function itself (e.g., a network call, or a read from disk) are harder to memoize, though it can still be done. But any function that is entirely deterministic is a good candidate.
  2. The function is computationally expensive. Meaning, when we run it, it generally takes a long time to return an answer. Any function involving math operations, especially in Python, tends to be expensive. Caching and reusing the results is often orders of magnitude faster than recomputing the results each time.

lru_cache basics

To memoize a function in Python, we can use a utility supplied in Python’s standard library—the functools.lru_cache decorator.

lru_cache isn’t hard to use. The above example would be memoized with lru_cache like this:

Copyright © 2021 IDG Communications, Inc.

Source link