Function Repository Resource:

LimitedCache

Source Notebook

Cache computations like Once but with a maximum number of cached values

Contributed by: Jon McLoone

ResourceFunction["LimitedCache"][expr]

evaluates expr and store results in the "Default" or return previously cached results.

ResourceFunction["LimitedCache"][expr,n]

caches the result of expr setting the maximum cache size to n, if this is a new cache.

ResourceFunction["LimitedCache"][expr,n,name]

caches the result of expr in a cache labeled name.

ResourceFunction["LimitedCache"]["Reset"]

removes the contents of the "Default" cache and set the maximum number of items to store to 100.

ResourceFunction["LimitedCache"]["Reset",n,name]

removes the contents of cache and reset the maximum number of items to store.

ResourceFunction["LimitedCache"]["State",name]

returns the DataStructure representing the cache state.

Examples

Basic Examples (3) 

The first time LimitedCache is used, the value is computed:

In[1]:=
ResourceFunction["LimitedCache"][Print["Evaluating"]; 2 + 2]
Out[1]=

No evaluation is performed when the computation result is in the cache from a previous calculation:

In[2]:=
ResourceFunction["LimitedCache"][Print["Evaluating"]; 2 + 2]
Out[2]=

By default, a maximum of 100 values will be cached, so evaluations that get discarded will be recomputed:

In[3]:=
Table[With[{i = i}, ResourceFunction["LimitedCache"][2 + i]], {i, 100}]
Out[3]=
In[4]:=
ResourceFunction["LimitedCache"][Print["Evaluating"]; 2 + 2]
Out[4]=

Scope (2) 

The first use of LimitedCache sets the size of the cache:

In[5]:=
ResourceFunction["LimitedCache"][2 + 2, 1000]
Out[5]=
In[6]:=
ResourceFunction["LimitedCache"][2 + 2, 10]
Out[6]=
In[7]:=
ResourceFunction["LimitedCache"]["State"]["Capacity"]
Out[7]=

You can change the cache size, in which case all previously cached values will be discarded:

In[8]:=
ResourceFunction["LimitedCache"]["Reset", 200]
ResourceFunction["LimitedCache"]["State"]["Capacity"]
Out[9]=

By default all cached values share the same cache with least recently used values being discarded first. If you need to maintain separate caches for different tasks you can provide a cache name:

In[10]:=
ResourceFunction["LimitedCache"][Print["Evaluating"]; 2 + 2, 10, "first"]
Out[10]=
In[11]:=
ResourceFunction["LimitedCache"][Print["Evaluating"]; 2 + 2, 3, "second"]
Out[11]=
In[12]:=
{ResourceFunction["LimitedCache"]["State", "first"]["Capacity"], ResourceFunction["LimitedCache"]["State", "second"]["Capacity"]}
Out[12]=

The data is stored in a DataStructure. This can be accessed directly and supports all operations supported by the "LeastRecentlyUsedCache” DataStructure:

In[13]:=
ResourceFunction["LimitedCache"]["State", "first"]
Out[13]=
In[14]:=
ResourceFunction["LimitedCache"]["State", "first"]["Values"]
Out[14]=

Applications (2) 

The typical application is to memoize function evaluations that are likely to be repeated many times. For example this double-recursive method for calculate Fibonacci numbers recomputes many values:

In[15]:=
fib[0] = 0; fib[1] = 1;
fib[n_] := fib[n - 1] + fib[n - 2];
AbsoluteTiming[fib[32];]
Out[15]=

By caching some of the values, you can prevent much of the recursion and improve the evaluation time:

In[16]:=
fib[0] = 0; fib[1] = 1;
fib[n_] := ResourceFunction["LimitedCache"][fib[n - 1] + fib[n - 2], 20];
AbsoluteTiming[fib[32];]
Out[16]=

Properties and Relations (1) 

LimitedCache has the same purpose as Once except that Once will typically require more memory the more that it is used, while LimitedCache does not:

In[17]:=
start = MemoryInUse[];
Do[With[{i = i}, Once[RandomReal[i]]], {i, 10^4}];
MemoryInUse[] - start
Out[17]=
In[18]:=
start = MemoryInUse[];
Do[With[{i = i}, ResourceFunction["LimitedCache"][RandomReal[i]]], {i,
    10^4}];
MemoryInUse[] - start
Out[18]=

Publisher

Jon McLoone

Version History

  • 1.0.0 – 24 June 2022

Related Resources

License Information