Implements BoundedSet
, a reimplementation of Set
specialised for storing integers bounded by a maximum value.
Let's say you want to keep track of some numbers, and efficiently answer questions like "have I seen this number?". You could use:
- an array--but then lookups are linear time
- an Object--lookups are now constant time, but it's not super-fast, and the keys have to be strings
- or a native
Set
(best).
If you know the maximum possible number up front, you can use bounded-set. BoundedSet
works like JavaScript's native Set
, except it's a few times faster. If you need a high-performance data structure, use this!
The API is similar to the Set
class, except you must give the bound as the first argument:
const BoundedSet = require('bounded-set')
let s = new BoundedSet(1000)
s.add(42)
s.has(42) // true
Accessing an integer over the bound is not allowed.
b.has(1001) // Error: out of bounds: 1001
b.has(-1) // Error: out of bounds: -1
The bound is inclusive.
BoundedSet
is more than twice as fast as a native Set.
- Inserts and deletes are about ~3x faster than a native Set.
- Lookups are about ~2-3 faster than a native Set.
- Iteration is 25% faster than a native Set (depending on bound); half the speed of
about twice as fast asarray iteration usingforEach
; and 20x faster than usingObject.keys()
... :-)
It used to be a bit faster still, but Set
s have caught up... the V8 team do good stuff :-)
Supports IE10+. (JS Set
supports IE11+.)
The following subset of the Set
API is supported:
add(item)
delete(item)
has(item)
-> Booleanvalues()
-> Array of values, instead of the nativeSetIterator
size
-> Number
Not supported:
- Iterators (feel free to send a PR!)
The implementation uses a bitmask of 32-bit unsigned integer words. A 1
bit indicates the number is in the set.
This leads to an obvious downside: memory use. Since we allocate one bit for each number up to the bound; allocating a BoundedSet with a bound of 2^30 (the largest sensible bound in JavaScript; remember JS only has Doubles)--will allocate a buffer 134MB in size.
It's also not actually faster for sufficiently large bounds. You should be safe up to at least 2^16 (65536). Somewhere above 2^14, iteration starts to get slow. But this probably depends on your hardware!