20110909

Caching Calculations in Javascript

I've been asked to demonstrate a solution to a small problem using JavaScript. The problem is basically one of scope and calculation caching, and is defined thusly:
I have two functions that perform calculations. Function A is always called before function B, and function B always calls function A. How can I make this more efficient?
Of course there's probably a way to solve this problem through refactoring the code, but let's pretend there isn't in our scenario. Javascript is a prototypal language, not a class based one. Fortunately for us, this means we can create a function and then attach properties to it that make it behave somewhere between a true function and an object. On to the code...

Internally Managed Data Caching
If a function performs heavy calculations, you really don't want it to perform the calculations over and over again, especially not while the parameters are the same. The following function employs caching to make its execution more efficient:


function A()
{
     if (A.cache === false)
     {
          // Our super complex calculation
          A.cache = 1 + 2 + 3 + 4;
     }
     return A.cache;
}

// Define a static variable that is local to the A function that
// will store the result of the super complex calculations.
A.cache = false;

In the above example, we've made a function and a property attached to that function that is used to store the result of a calculation. The first time the function is executed, the cache container "A.cache" property is set to 'false' which triggers the calculation to be performed. But notice that instead of simply returning the value of the calculation, we cache it. Since the function is always returning the cached calculation, it can be called as many times as you want, but it will only perform the calculation once. So with the problem stated above, you could call function A, then function B knowing full well that function A will get called a total of two times, but will only do any actual work once.

Externally Managed Data Caching
How can you force the function to refresh its cache if there's no way to tell it that the environment changed in such a way that the result of the calculation could be different? What you really need is a mechanism for informing the function that its cache is dirty and needs to be refreshed. This could technically be done by setting A.cache = false, but here's a slightly more robust example.

function A()
{
     if (A.cache === false || A.cacheIsDirty !== false)
     {
          // Our super complex calculation
          A.cache = 1 + 2 + 3 + 4;
          A.cacheIsDirty = false;
     }
     return A.cache;

}


// Define a static variable that is local to the A function that
// will store the result of the super complex calculations.
A.cache = false;

// Define a static variable that is local to the A function that
// will be used to inform function A that its cache is not to be
// trusted.
A.cacheIsDirty = true;

And done! We've now got a way for outside code to warn a function that its internal cache may no longer be safe to use. A simple use case for this might be a form wherein a user can input multiple parameters and then view the calculations. Well, if the user doesn't modify any of the parameters that function A might need to look at, then it should be allowed to return the cached result. But if the user does change a parameter that function A cares about, then the piece of code that was listening for that change can call A.cacheIsDirty = true; to make sure that function A will discard its cache and run its calculations again.

0 comments: