Skip to content

Boosting Performance with Memoization: The Power of Caching for Efficient Computing

Published: at 15:28

Examples can be found in my GitHub repository.

Table of contents

Open Table of contents

Introduction

In this blog post, we will explore the concept of memoization and how it can be used to optimize code performance. We will discuss the benefits of memoization and how it can be implemented in JavaScript applications to improve speed and efficiency.

What is memoization?

Memoization is a technique used to optimize the performance of functions by caching the results of expensive computations. When a function is memoized, the results of its computations are stored in a cache, allowing subsequent calls to the function with the same inputs to return the cached result instead of re-computing it. This can greatly improve the speed and efficiency of the function, especially when it is called with the same inputs multiple times.

How does memoization work?

When a function is memoized, the results of its computations are stored in a cache. The cache is typically implemented as a key-value store, where the inputs to the function are used as keys and the results of the computations are stored as values. When the function is called with a set of inputs, the cache is checked to see if the result for those inputs is already stored. If it is, the cached result is returned. If not, the function is called to compute the result, which is then stored in the cache for future use.

Example of memoization in JavaScript

Take an example of a search function that takes a query string as an input, calls an API to fetch search results, and returns the results. If the search function is called with the same query string multiple times, the results of the API call can be memoized to avoid redundant API calls and improve the performance of the function.

function fetchData({ query }: FetchDataParams): Promise<Location[]> {
  return new Promise<Location[]>((resolve) => {
    if (query.length) {
      const fromCache = getFromCache(query) as Location[];
      if (fromCache) {
        resolve(fromCache);
        return;
      }

      getLocation(query).then((data) => {
        addToCache(query, data.results);
        resolve(data.results);
      });
    }
  });
}

In this example, the fetchData function fetches location data from an API based on a query string. If the results for a particular query are already stored in the cache, they are returned using the getFromCache function. If not, the API is called to fetch the results, which are then stored in the cache using the addToCache function. Try searching for the same movie title multiple times to see the performance improvement.

Here is a simple implementation of the cache:

const cache = new Map<string, any>();

function getFromCache(key: string) {
  return cache.get(key);
}

function addToCache(key: string, value: any) {
  cache.set(key, value);
}

Benefits of memoization

Memoization can provide several benefits to JavaScript applications, including:

Implementing memoization in React

useMemo hook

In a React application, memoization can be implemented using the useMemo hook to cache the results of expensive computations. The useMemo hook takes a function and an array of dependencies as arguments and returns the memoized result of the function. If the dependencies change, the function is called to recompute the result, which is then stored in the cache for future use.

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

In this example, the computeExpensiveValue function is called with the inputs a and b, and the result is memoized using the useMemo hook. If a or b change, the function is called to recompute the result, which is then stored in the cache for future use.

useCallback hook

The useCallback hook can also be used to memoize functions in a React application. The useCallback hook takes a function and an array of dependencies as arguments and returns a memoized version of the function. If the dependencies change, the function is called to recompute the result, which is then stored in the cache for future use.

const memoizedCallback = useCallback(() => {
  doSomething(a, b);
}, [a, b]);

In this example, the doSomething function is memoized using the useCallback hook. If a or b change, the function is called to recompute the result, which is then stored in the cache for future use.

Difference between useMemo and useCallback

The useMemo and useCallback hooks are similar in that they both memoize the results of functions. However, they are used for different purposes:

Conclusion

Memoization is a powerful technique for optimizing the performance of functions by caching the results of expensive computations. In JavaScript applications, memoization can greatly improve the speed and efficiency of functions, especially when they are called with the same inputs multiple times. By using the useMemo and useCallback hooks in a React application, memoization can be implemented to improve the performance of values and callbacks, making the code faster and more efficient.