• Stars
    star
    108
  • Rank 321,259 (Top 7 %)
  • Language
    JavaScript
  • License
    MIT License
  • Created over 7 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Unabashedly-barebones memoization library with an aim toward speed

Memize

Memize is a unabashedly-barebones memoization library with an aim toward speed.

Why use Memize?

  • πŸš€ It's very fast. Implemented as a least recently used (LRU) cache, it's heavily optimized for scenarios where the function is called repeatedly with the same arguments.
  • πŸ”¬ It's tiny. It weighs in at less than 0.3kb minified and gzipped, with no dependencies.
  • πŸ”€ It supports common arguments patterns, including multiple arguments and non-primitive arguments (by reference).

Example

Simply pass your original function as an argument to Memize. The return value is a new, memoized function.

function fibonacci( number ) {
	if ( number < 2 ) {
		return number;
	}

	return fibonacci( number - 1 ) + fibonacci( number - 2 );
}

var memoizedFibonacci = memize( fibonacci );

memoizedFibonnaci( 8 ); // Invoked, cached, and returned
memoizedFibonnaci( 8 ); // Returned from cache
memoizedFibonnaci( 5 ); // Invoked, cached, and returned
memoizedFibonnaci( 8 ); // Returned from cache

Installation

Using npm as a package manager:

npm install memize

Usage

Memize accepts a function to be memoized, and returns a new memoized function.

memize( fn: Function, options: ?{
	maxSize?: number
} ): Function

Optionally, pass an options object with maxSize defining the maximum size of the cache.

The memoized function exposes a clear function if you need to reset the cache:

memoizedFn.clear();

Benchmarks

Implemented as a least recently used (LRU), Memize is heavily optimized for scenarios where the function is called repeatedly with the same arguments. In these scenarios, Memize outperformed most other memoization libraries at the time of initial publication.

To learn more about these benchmarks, important caveats, and how to run them yourself, refer to benchmark/README.md.

How it works

If you haven't already, feel free to glance over the source code. The code is heavily commented and should help provide substance to the implementation concepts.

Memize creates a last-in first-out stack implemented as a doubly linked list. It biases recent access favoring real-world scenarios where the function is subsequently invoked multiple times with the same arguments. The choice to implement as a linked list is due to dramatically better performance characteristics compared to Array#unshift for surfacing an entry to the head of the list (jsperf). A downside of linked lists is inability to efficiently access arbitrary indices, but iterating from the beginning of the cache list is optimized by guaranteeing the list is sorted by recent access / insertion.

Each node in the list tracks the original arguments as an array. This acts as a key of sorts, matching arguments of the current invocation by performing a shallow equality comparison on the two arrays. Other memoization implementations often use JSON.stringify to generate a string key for lookup in an object cache, but this benchmarks much slower than a shallow comparison (jsperf).

Finally, special care is made toward treatment of arguments due to engine-specific deoptimizations which can occur in V8 via arguments leaking. Order is important here; we only create a shallow clone when necessary, after the cache has been checked, to avoid creating a clone unnecessarily if a cache entry exists. Looking at the code, you'd not be blamed for thinking that dropping the shallow clone would improve performance, but in fact it would slow execution by approximately 60%. This is due to how the lingering arguments reference would carry over by reference ("leaks") in the node's args property. Update: As of November 2019, engine improvements are such that arguments leaking does not have as dramatic an effect. However, my testing shows that the shallow clone still performs equal or better than referencing arguments directly, and as such the implementation has not been revised in order to achieve optimal performance in the most versions of V8.

License

Copyright 2018-2020 Andrew Duthie

Released under the MIT License.

More Repositories

1

hpq

Utility to parse and query HTML into an object shape
TypeScript
96
star
2

dones

Simple team task management and tracking
JavaScript
68
star
3

correctingInterval

An auto-correcting alternative to setInterval
JavaScript
57
star
4

rememo

Memoized selectors for Redux and other immutable object derivation
JavaScript
17
star
5

refx

Redux middleware for triggering side effects
JavaScript
11
star
6

tannin

gettext localization library compatible with Jed-formatted locale data
JavaScript
11
star
7

Doom_CooldownPulse

A World of Warcraft addon that animates ability icons when they are available to be used after cooldown
Lua
10
star
8

react-gettext

React components for gettext-based internationalization
JavaScript
10
star
9

StreamLens

Browser extension for displaying live stream status for Twitch
TypeScript
10
star
10

grunt-jquerymanifest

Generate jQuery plugin manifest automatically from package.json values
JavaScript
9
star
11

hijinks

Tiny DOM builder utility inspired by HyperScript
JavaScript
7
star
12

preact-fetching

Preact hooks for asynchronous data fetching
JavaScript
7
star
13

g-debugger

Visual debugging tools for block development
JavaScript
6
star
14

Stopwatch.js

A minimal cross-platform stopwatch
JavaScript
6
star
15

resolve-entry-modules-webpack-plugin

Webpack plugin for considering each entry's enclosing directory as a resolve root
JavaScript
6
star
16

wp-block

Post editor blocks support for WordPress
JavaScript
6
star
17

preact-jsx-runtime

Preact JSX runtime definition for use with automatic JSX import
JavaScript
6
star
18

regimen

πŸ’ͺ🏼 Workout progression planning web app
JavaScript
5
star
19

Ghat

Relay GitHub events to your favorite chat client
JavaScript
4
star
20

turbo-combine-reducers

⚑️ Speed-optimized drop-in replacement for Redux's combineReducers
JavaScript
4
star
21

equivalent-key-map

A Map variant which allows for equivalent (deeply equal) object and array keys
JavaScript
3
star
22

express-mongoose-starter

A very bare-bones starter app, using only Express and Mongoose.
JavaScript
3
star
23

crawl-domain

Crawl to discover all paths under a given URL domain
JavaScript
3
star
24

esbuild-esm-loader

ESM loader to transform imports using ESBuild
JavaScript
3
star
25

react-async-flux

Boilerplate for async data flow using React and Redux
JavaScript
3
star
26

esm-root-loader

ESM loader to import from the project root
JavaScript
3
star
27

calypso-gmcourse-snippets

JavaScript
3
star
28

jquery.passwordMask

jquery.passwordMask is a jQuery plugin to allow users the ability to toggle password masking
JavaScript
2
star
29

handlebars-helper-filehash

{{ fileHash }} Handlebars helper for generating an md5 hash from a file's content
JavaScript
2
star
30

github-explorer

Embeddable GitHub file explorer
JavaScript
2
star
31

jcarousel-smoothscroll

Animates a jCarousel at a constant pace, regardless of varying item widths
JavaScript
2
star
32

wordcamp-popular-movies

JavaScript
2
star
33

wping

WordPress nonce refresh utility
JavaScript
2
star
34

wp-elements

Elements DOM builder support for WordPress
PHP
2
star
35

Toupee

An experimental bill tracking application inspired by TodoMVC
JavaScript
2
star
36

serve-static-cache

Express middleware for writing responses to static files
JavaScript
1
star
37

andrewduthie.com

The personal website of Andrew Duthie
JavaScript
1
star
38

prsh

Preact Redux Simple Hooks
JavaScript
1
star
39

LibroIpsum

Generates phrases using character distribution of text
JavaScript
1
star
40

small

A blogging application aimed at providing a minimal, fast, and easy-to-use interface for expressing your ideas to the world. Under the hood, it is built as an isomorphic JavaScript application powered by WordPress.com.
JavaScript
1
star
41

wordpress-core-styles

Styles for WordPress generated classes, including alignment and captions
CSS
1
star
42

dones-cli

Record Dones tasks from your terminal
JavaScript
1
star
43

ipfs.casa

Upload to the distributed web
JavaScript
1
star
44

ArenaFilter

World of Warcraft addon to add class and role filtering options to the premade arena group finder
Lua
1
star
45

uTip

A small JavaScript utility for displaying simple, elegant tooltips
JavaScript
1
star
46

crawl-sitemap

Crawl to discover all URL locations defined in a sitemap or sitemap index
JavaScript
1
star
47

jquery.imposeFormat

Unobtrusively impose a consistent format on form inputs
JavaScript
1
star
48

dones-idonethis-importer

Import iDoneThis tasks to the Dones theme
PHP
1
star
49

sass-embedded-cli

Command-line interface for sass-embedded
JavaScript
1
star