Skip to content
David Nolen edited this page Jan 16, 2015 · 18 revisions

Mori now provides an API suitable for benchmarking its persistent data structure from plain JavaScript. Operations like mori.assoc are variadic and internally dispatch to the correct arity handler function through the length of arguments, the overheads incurred are very measurable. In ClojureScript removing this overhead is performed statically via the compiler, however this cannot be automated for JavaScript consumers. To eliminate this overhead Mori now supports direct invocation of function arities by exporting a simple direct api.

var m = require("mori"),
    h = m.hashMap();

m.assoc(h, "foo", "bar"); // indirect
m.assoc.f3(h, "foo", "bar"); // direct

The convention is simply fN where N is some integer representing the arity. Note some functions only have a single defined arity and a fN direct invocation will not be available.

Calling into Mori still has overheads likely not to be present in pure JavaScript persistent data structure libraries: factory functions copy arguments into an array and wrap in immutable data structure, and critical entry points like nth and get invoke a series of invariant checks, type checks, and custom polymorphic dispatch.

Here is a complete example comparing Mori using the direct API and Immutable.js:

var m = require("mori"),
    Immutable = require("immutable");

function time(f, iters) {
    iters = iters || 1;
    for(var i = 0; i < iters; i++) {
        var s = new Date();
        f();
        console.log("Elapsed "+((new Date()).valueOf()-s.valueOf())+"ms");
        console.log("----------");
    }
}

// ~180ms Node 0.10.35, 2.26ghz 2010 MBP
time(function() {
    var hm = m.hashMap();
    for(var i = 0 ; i < 100000; i++) {
        for(var j = 0; j < 8; j++) {
            hm = m.assoc.f3(hm, "foo"+j, j);
        }
    }
}, 1);

// ~2000ms
time(function() {
    var hm = Immutable.Map();
    for(var i = 0 ; i < 100000; i++) {
        for(var j = 0; j < 8; j++) {
            hm = hm.set("foo"+j, j);
        }
    }
}, 1);

// ~330ms
time(function() {
    var v = m.vector();
    for(var i = 0 ; i < 1000000; i++) {
        v = m.conj.f2(v, i);
    }
}, 1);

// ~2500ms
time(function() {
    var l = Immutable.List();
    for(var i = 0 ; i < 1000000; i++) {
        l = l.push(i);
    }
}, 1);

// ~80ms
time(function() {
    var v = m.mutable.thaw(m.vector());
    for(var i = 0 ; i < 1000000; i++) {
        v = m.mutable.conj.f2(v, i);
    }
    v = m.mutable.freeze(v);
}, 1);

// ~500ms
time(function() {
    var l = Immutable.List().asMutable();
    for(var i = 0 ; i < 1000000; i++) {
        l = l.push(i);
    }
    l.asImmutable();
}, 1);
Clone this wiki locally