What’s memoization all about? First off, memoization is a technique where you cache the results of expensive function calls so that when the same input occur again, you can return the cached result instead of recalculating it again.
Let’s get into a simple example of this.
|
|
This simple example is expensive because this recursive function will run for whatever the value N is. Specifically, this function has a time complexity of O(2^n). This means that the speed of this function will exponentially grow for each call it has to make.
For example, if we say n
is equal to 8 then this function would be called 54 times! That’s a lot!
Now if I were to improve the performance of this method by using memoization, I would want to include a cache within the function that would hold all previous attempts. Let’s see how this is implemented
|
|
So much better! Now if we were to say that n is equal to 8 for this method, it would be change the time complexity to O(n). A significant improvement! Now this results in 9 function calls! To put it another way, the number of calls grow linearly instead of exponentially.
Let’s expand on this and see how this can be used in the real world!
We’re going to write a function that fetches data from some API.
|
|
This is great! We can see that memoization is a great use case for reducing redundant API calls to the backend which makes the application run faster. This end up reduces the load on the backend as well.
We can continue to improve upon this! We can introduce an expiry time to each cached element. Along with keeping things efficient, we are also making sure that the data we are requesting doesn’t go stale.
Let’s implement this:
|
|
Generally memoization is a good pattern to use when:
- You have expensive recursive functions
- You have a function that are performing costly operations repeatedly with the same inputs
- API calls and network requests
- Parsing and processing large data
- UI rendering optimizations
and for some real world examples
- user data processing
- Form validation
- Search functions
- Rendering complex UI components
- Route calculations (? what)
Memoization isn’t always the answer! Here’s a few times when it’s not a good pattern to implement:
- Simple, fast operations
- Using impure functions
- Inputs that are rarely repeated
- Time sensitive or real time data.
- If the cached results consumes more memory than what it costs to compute
Thanks for reading!