Fast javascript memoize function, with optimized memoize strategies provided. Class
and methods memoize decorators.
npm i -S auto-memoize
// memoize functionlet memoizeFibonaci = //cache hit // Create one instance with same parameters@CreateOnce firstName lastName { console thisfirstName = firstName thislastName = lastName } // call method once with same parameters @CallOnce { console const name = ` ` return name greeting }const person1 = 'Boris' 'Johnson' // logged 'Creating Boris Johnson'const person2 = 'Boris' 'Johnson'person1 == person2 // true const g1 = person1 // logged 'hi'const g2 = person1g1 == g2 // true
memoize
Default implementation
Caches by all parameters as a key, comparing them with Object.is
algorithm
const calc = const memoize = const memoCalc = const param = a: 'one' // cache hit // no cache hit, because reference is different
WeakMap implementation
Caches by first parameter as a key and using ES6 WeakMap as a cache. Garbage collector automatically removes entries from cache, when no references for keys are present.
const calc = const memoize = const memoCalc = const param = a: 'one' // cache hit // no cache hit, because reference is different
Deep comparison implementation
Caches by all parameters as a key and compares them by content, if references are different.
fast-deep-equal
npm package does the comparison.
It is performing better on big objects, than JSON.stringify
.
const calc = const memoize = const memoCalc = const param = a: 'one' // cache hit // cache hit
String key implementation
Caches all parameters as a string key. For cache is used
ES6 Map. JSON.stringify
is used to turn every parameter to string. It is useful for function with several parameters, but not big objects, that takes time to turn into string
.
const calc = const memoize = const memoCalc = const param = a: 'one' // cache hit // cache hit
Custom key implementation
Caches by key from function, that returns string
. For cache is used ES6 Map
const calc = const memoize = const memoCalc = const param = a: 'one' // cache hit // cache hit
Benchmarking strategies
Small object parameter
const simple = data: p1: name: 'auto-memoize'
Strategy | ops/sec | |
---|---|---|
1 | callback | 4,765,946 |
2 | weak | 3,751,169 |
3 | deep | 1,211,864 |
4 | default | 1,004,562 |
5 | string | 341,206 |
Object parameter
const data = ...3 packagejson
Strategy | ops/sec | |
---|---|---|
1 | callback | 5,131,611 |
2 | weak | 2,663,508 |
3 | default | 992,947 |
4 | deep | 832,758 |
5 | string | 33,763 |
Different reference object parameter
const data = ...3 packagejson
Strategy | ops/sec | ||
---|---|---|---|
1 | callback | 2,195,159 | |
2 | deep | 708,301 | |
3 | string | 33,098 | |
weak | 833,162 | n/a | |
default | 1,484 | n/a |
Primitive parameters
Strategy | ops/sec | ||
---|---|---|---|
1 | callback | 3,340,699 | |
2 | deep | 1,320,397 | |
3 | default | 1,330,912 | |
4 | string | 548,254 | |
weak | n/a |
Typings includes types for:
- memoized function parameters
- memoized function return type
getCache
Utility function to get cache instance from memoized function, class or method.
It will return instance of CacheMap
. It enables you to retrieve cache records and invalidate cache.
CacheMap
For different cache strategies different keys are applicable. Key types:
- default -
any[]
- weak -
object
- string -
string
(parameters joined by-
) - deep -
any[]
- custom key -
string
Examples
const memo = // cache from meoized function // trueclear // false @CreateOnce { thisfirstName = firstName thislastName = lastName } @CallOnce { const firstName = this return greeting firstName }const person = 'A' 'B'person // cache from decorated 'CreateOnce' or 'CreateOnceBy' class // cache from decorated 'CallOnce' or 'CallOnceBy' class
Decorators
Docs
@CreateOnce
Class
Decorator used to create same instance of class when same parameters are passed.
It follows functional design pattern memoize, also Flyweight design pattern,
when one instance of Class
is created once with exact state.
It defines how objects with state can be shared.
If class constructor has no parameters, class decorated with CreateOnce
becomes singleton.
If this class is extended, effect of decorator will be applied on child classes. Parent constructor will always be constructor that creates class instance. Even if child
constructor accepts different parameters.
If child class is decorated, child class will have cache effect.
It will cache instances by default 'auto-memoize' strategy.
Decorator @CreateOnceBy can be configured with other cache hit strategy
@CreateOnceBy
Class
Decorator used to created same instance of class when same parameters are passed.
It follows functional design pattern memoize, also Flyweight design pattern,
when one instance of Class
is created once with exact state.
It defines how objects with state can be shared.
It will cache instances by strategy from decorator parameter.
Decorator @CreateOnce is preconfigured with default cache hit strategy.
If this class is extended, effect of decorator will be applied on child classes. Parent constructor will always be constructor that creates class instance. Even if child
constructor accepts different parameters.
If child class is decorated, child class will have cache effect.
@CallOnce
Class
method decorator used to create memoized class method. Method that will return
same output with same parameters passed. It follows memoize functional design pattern.
It will cache by default auto-memoize
strategy.
Decorator @CallOnceBy can be configured with other cache hit strategy.
@CallOnceBy
Class
method decorator used to create 'memoized' class method. Method that will return
same output with same parameters passed. It follows memoize functional design pattern.
It must be configured with cache hit strategy.
Decorator @CallOnce is already preconfgured with default strategy.
Examples
Caching with default strategy
; // Creates one class instance per constructor parameter @CreateOnce greeting { thisgreeting = greeting } // Calls method once per parameter unique // method with cache @CallOnce { return greet: `, !` } const greeter1 = 'Hello'const greeter2 = 'Hello'greeter1 == greeter2 // true const greet1 = greeter1const greet2 = greeter1const greet3 = greeter2greet1 == greet2 // truegreet1 == greet3 // true
Caching with provided strategy
; // Creates one class instance per constructor parameter @ greeting { thisgreeting = greeting } // Calls method once per parameter unique // method with cache @ { return greet: `, !` } const greeter1 = 'Hello' const greeter2 = 'Hello' greeter1 == greeter2 // true const greet1 = greeter1 const greet2 = greeter1 const greet3 = greeter2 greet1 == greet2 // true greet1 == greet3 // true
Class Singleton
; // Always will return same instance of class@CreateOnce { } { return greet: `Hello, !` }const greeter1 = const greeter2 = greeter1 == greeter2 // true