I recently caught up on some technical reading. I’m particularly enjoying posts related to functional programming. One downside to functional programming is the performance hit we take jumping scope and making extra function calls for things we could just do in a single block.

One of the more interesting ideas in functional programming is composition. The idea that you can combine two steps, like y = g(x); and z = f(y); into a single function z = f(g(x));. The typical compose function example I see takes two arguments, like the one in chapter 6 of Eloquent JavaScript. If you want to compose a third function, you have to call compose again, z = compose(e, compose(f, g));.

This type of nesting is precisely the scope chaining we don’t need (provided we know all of the functions to compose). For instance, a compose function designed to take three arguments, z = compose(e, f, g), will outperform the two calls to the compose function with arity of two. So, based on my work with get, I wrote a memoizing compose that takes any number of functions.

some simple examples of usage:

EDIT: Based on feedback from a colleague, I removed memoize and used spaces instead of ‘\t’ in c to make the implementation more clear and less distracted. The old version is still in my gists, #4747439.

A sparse array is an instance of Array that has undefined as one or more members. I’ve seen them used, for performance reasons, in game engines to pre-allocate a buffer. I believe it has something to do with one versus two operations–altering a member versus adding a member and increasing length. But there are other uses for them if you know what you can and can’t do with them.

Ways to create sparse arrays:

  1. Array(n) where n is an integer, will create an array with n undefined members
  2. Alter the length property of an existing array (with fewer members than the new length): var arr = []; arr.length = 1;
  3. Delete a member from an existing array, or by deleting a member. var arr = [1,2,3]; delete arr[1];
  4. Set a member of an existing array to undefined. var arr = [1,2,3]; arr[1] = void(0);
  5. Create an array literal with commas and no value: var arr = [,,,];

A co-worker was trying to make a repeating string and used a sparse array; it looked something like this:

var arr = Array(9);
var str = ""; 
arr.forEach(function () {
    str += "\<td\>\<\/td\>";
});
 
//another attempt
arr.map(function () {
    return "\<td\>\<\/td\>";
});

Both statements fail for the same reason: the JavaScript engine does not iterate over undefined members of an array. Iteration based on length, like typical for and while loops, work fine. But .forEach and .map work like for-in which skips the undefined member(s).

//setup
var arr = [];
arr.length = 10;
arr[5] = "";
var count = 0;
 
//test for
var i, len;
for (i = 0, len = arr.length; i < len; i += 1) {
    count += 1;
}
console.log(count); //10
 
//test while
count = 0;
var i = arr.length;
while (i--) {
    count += 1;
}
console.log(count); //10
 
//test for-in
var i, count = 0;
for (i in arr) {
    count += 1;
}
console.log(count); //1
 
//test forEach
var count = 0;
arr.forEach(function () {
    count += 1;
});
console.log(count); //1
 
//test map
var count = 0;
arr.map(function () {
    count += 1;
});
console.log(count); //1

I came up with some variations of this idea that work (seen here: jsPerf). The test task was to write code that will inject a “test” td at the fourth position of 9 (otherwise empty) td’s. Some are quite nice syntactically, but none seem to perform like a for loop. This one was my favorite for its simplicity.

Array.prototype.join.call({3: "<td>test</td>", length: 9}, "<td></td>");

My main project at work uses large JavaScript objects for a data store. Our team used a very cool method to dynamically create null-safe getter functions and cache them for reuse. Oh, and did I mention it was fast?

I rewrote the guts to do just the bare minimum*–get objects and their primitive property values from a given context (or this). Future implementations may take some sort of descriptive notation in the path (mostly likely to filter arrays of objects), but this will work well for most applications.

* note: So, slightly more than the bare minimum. I chose to allow path to be a string or array of strings. This allows me to pass get.apply an arguments object–which may come in handy–and saves processing if I already have a split path.

/**
 * null-safe retrieval of objects and their property values from context
 * @function get
 * @param {String|String[]} path
 * @param {Object} [obj=this]
 * @return
 */
(function (HEAD) {
    var depthCache = {};
    var cache = {};
    function getDepth(depth) {
        if (!depthCache[depth]) {
            var params = "";
            var vars = "  var _0 = this";
            var body = false;
            var h, i;
            for (i = 0; i < depth; i += 1) {
                params += i ? (", $" + i) : "$" + i;
                vars += i ? (", _" + i) : "";
            }
            vars += ";\n";
            for (h = i - 1; i > 0; i -= 1, h -= 1) {
                if (!body) {
                    body = "_" + h + " === Object(_" + h + ") && ($" + h + " in _" + h + ") ? _" + h + "[$" + h + "]";
                } else {
                    body = "(_" + i + " = _" + h + "[$" + h + "], _" + i + ") && " + body;
                }
            }
            body = "  return " + (!body ? "_0;" : body + " : void(0);");
            depthCache[depth] = Function(params, vars + body);
        }
        return depthCache[depth];
    }
    function get(path, obj) {
        var params = path ? path.split ? cache[path] || (cache[path] = path.split("."), cache[path]) : path : [];
        return getDepth(params.length).apply(obj || this, params);
    }
    HEAD.get = get;
}(this));

tests after the break:
Continue reading

While writing a handler for key events, I realized I was having to convert the event’s key data to test for valid inputs every time. I wondered if using a list of valid inputs would be faster than checking a regular expression.

Here’s a quick test:
http://jsperf.com/regexp-vs-indexof2

Not surprisingly, Chrome was fast enough in both cases and RegExp was slightly faster. Surprisingly, IE and FF were much faster for indexOf with FF running the index test as fast as Chrome’s RegExp results.

So I went further in the test, creating actual handlers with jQuery:
http://jsperf.com/handle-keypress

$("#indexof").on("keypress", (function () {
    var str = ",";
    var i;
    for (i = 65; i &lt; 91; i += 1) {
        str += i + ",";
    }
    return function (evt) {
        if (str.indexOf("," + evt.charCode + ",") &lt; 0) {
            evt.preventDefault();
        }
    };
}()));
 
$("#regexp").on("keypress", function (evt) {
    if (/[A-Z]/.test(String.fromCharCode(evt.charCode)) === false) {
        evt.preventDefault();
    }
});

In this test, far too much time is spent dealing with the event and not enough time just working out the keypress so there appears to be no winner. Based on syntactic brevity, the RegExp is the clear choice. However, if you need to control characters other than those easily expressed in RegExp (like control characters or unicode), you might try the indexoOf method with no loss in performance.

While reading the answers to Nathan Smith’s JavaScript Quiz, I was struck by the number of assumptions made around decimal precision.  In two places, the author states “you need to multiply values by 10” when in actuality, you need to multiply values by the precision’s power of ten.

That lead me to write this bit of code to illustrate how you might handle high precision numbers (and of varying precision) without using a separate library.

function getPrecision(num) {
    var split = (num + "").split(/([\.e\-]{1,2})/);
    var i, len, token, next, nextNum, precision;
    for (precision = 0, i = 1, len = split.length; i < len; i += 1) {
        token = split[i];
        next = split[i + 1];
        nextNum = +next;
        if (token === ".") {
            precision += next.length;
        } else if (token === "e-") {
            precision += i > 1 ? nextNum + 1 : nextNum;
            break;
        }
    }
    return precision;
}
 
function getMaxPrecision(arr) {
    var i, len, precision, max;
    for (max = 0, i = 0, len = arr.length; i < len; i += 1) {
        precision = getPrecision(arr[i]);
        max = (precision > max) ? precision : max;
    }
    return max;
}
 
function sumArgs() {
    var args = Array.prototype.slice.call(arguments);
    var max = getMaxPrecision(args);
    var pow = Math.pow(10, max);
    var i, len, sum, arg;
    for (sum = 0, i = 0, len = args.length; i < len; i += 1) {
        arg = args[i];
        sum += isNaN(arg) ? 0 : (arg * pow);
    }
    return sum / pow;
}
 
console.assert(getPrecision(1) === 0); //no decimal or e-
console.assert(getPrecision(1.1234567890) === 9); //zeros are dropped, just decimal
console.assert(getPrecision(1.1234567890123456) === 16); //longest without rounding
console.assert(getPrecision(0.1) === 1);
console.assert(getPrecision(0.12345678901234567) === 17); //longest without rounding
console.assert(getPrecision(0.0000000001) === 10); //no decimal, just e-
console.assert(getPrecision(0.00000000000000000000000000000000000000000000000000000123456789012345678) === 71);
console.assert(sumArgs(0.00002, 0.00001, 0.1, 0.02) === 0.12003);
console.assert(getPrecision(Math.min()) === 0); //Infinity
console.assert(getPrecision(1e-324) === 0);
console.assert(getPrecision(1e-323) === 323);

EDIT: My use of Math.pow made me curious if there was a faster way to build a big number, see the tests: http://jsperf.com/make-a-big-number/2

You may have noticed that in my last article, I mentioned I would rather loop through copying arguments than slice them. That came out of this research: jsPerf.

var args = [1,2,3,4], i,
    len = args.length,
    arr = new Array(len);
for (i = 0; i < len; i += 1) {
    arr[i] = args[i];
}

With relatively short lists, copying out performs slice by 4x or more (your browser mileage may vary). This is important for low-level frameworky things that get invoked a lot. Since well-designed methods often have signatures under 10 (hopefully way under 10), looping is faster in every browser I tested. Safari had the most interesting results in that copying was always faster. It makes me wonder how that native implementation really works.

Part of the technique is pre-allocating the array length you will copy into. That seems to make a difference in some browsers so it’s worth mentioning that I used that technique in my tests. I believe this makes a difference because the looping copy process does not need to change the allocated memory for the target array as we add new values. If that were the case, I would expect lower thresholds in the browsers where this matters, like Chrome, see jsPerf.

Lastly, I found an interesting jsPerf test around the same idea except I noticed they constructed the test incorrectly, testing the performance of function construction instead of just the cloning action. I rewrote the tests with what I learned from the other test into this one: jsPerf.

function clone(arr) {
    var i, len = arr.length,
        arr_clone = new Array(len);
    for (i = 0; i < len; i += 1) {
        arr_clone[i] = arr[i];
    }
    return arr_clone;
}

In conclusion, even when converted to a method, this technique can outperform native methods on short lists (although much less so). Given the smaller differences as a method, I would not advance the idea into a clone method on the Array prototype that switches techniques based on the current length–that additional logic would probably bring the overall speed down to native levels. Either copy in-line (only with small lists) or use a native method when performance matters.

By using a simple approach to curry and enforcing a strict signature and return value, we can make performance improvements to the traditional curry implementation.

Case 1:
Currying can be useful in JavaScript for making code DRYer and more reusable because you can create several derivative functions from a single function. This differs from Partial Application in that Curry always partially applies a single argument while Partial Application may fix, or bind, any number of arguments.

This subtle difference can lead us to some performance gains. For instance, look at Douglas Crockford’s classic extension to the Function prototype from his book, JavaScript: The Good Parts:

Function.prototype.curry = function () {
    var slice = Array.prototype.slice,
        args = slice.apply(arguments),
        that = this;
    return function () {
        return that.apply(null, args.concat(slice.apply(arguments)));
    };
};

Performance Improvement 1:
By using the full arguments list, Crockford allows for partial application of arguments in the returned function. While convenient, most uses of the curry method will probably only pass a single argument. If we swap “slice.apply...” for “[arguments[0]]“, curry only uses the first argument passed and we have no need of transforming arguments into an Array using the borrowed slice method.

We still can not use concat directly (the reason Crockford sliced his arguments in the first place) because lacks generic qualities, see Dr. Rauschmayer’s article, Array.prototype.concat is not generic. Although Rauschmayer fails to point out that by applying concat, you can achieve the desired effect–essentially unwrapping the arguments array into separate arguments to be concatenated.

//Sadly, this will now perform slower than Crockford's implementation because concat will receive a longer arguments list.
//an alternate using unshift instead will be about the same speed
Function.prototype.curry = function () {
    var f = this,
        args = [arguments[0]];
    return function () {
        return f.apply(null, Array.prototype.concat.apply(args, arguments));
    };
};

This leaves us with a for loop as an alternative to populating the args Array.

Also consider, Crockford prevents the original function from having a context with a null parameter passed first to apply(). If we only plan to curry a single parameter, we can pass a context for use during invocation.

Function.prototype.curry = function (arg, context) {
    var f = this,
        args = [arg],
        count = 1;
    return function () {
        var i, len;
        for (i = 0, len = arguments.length; i < len; i += 1, count += 1) {
            args[count] = arguments[i];
        }
        return f.apply(context, args);
    };
};

Case 2:
Ben Alman recently wrote a great article, Partial Application in JavaScript, only to fall into the same trap:

function curry(/* n,*/ fn /*, args...*/) {
  var n,
    aps = Array.prototype.slice,
    orig_args = aps.call( arguments, 1 );
 
  if ( typeof fn === 'number' ) {
    n = fn;
    fn = orig_args.shift();
  } else {
    n = fn.length;
  }
 
  return function() {
    var args = orig_args.concat( aps.call( arguments ) );
 
    return args.length < n
      ? curry.apply( this, [ n, fn ].concat( args ) )
      : fn.apply( this, args );
  };
}
 
var testFn = function (a, b, c, d) {
    return a + b + c + d;
};
 
curry(testFn)(1)(2)(3)(4); //10
curry(testFn)(1,2,3)(4); //10

Developers who shun augmenting the native prototypes will find Alman’s function especially attractive. Another convenience of this implementation, apart from allowing partial application, invokes the original function upon satisfying all arguments. For instance, compare the invocation syntax:

testFn.curry(1).curry(2).curry(3).curry(4)(); //10
curry(testFn)(1)(2)(3)(4); //10

While less verbose, one may find the dynamic nature of the return value troublesome to deal with. Consider a function you would like to curry which returns a function. How do you type check the results of calling curry? Additionally, while the optional “n” parameter may solve issues with functions which take n arguments, this complicates the maintenance of such code when curried functions change their signatures. By all definitions I can find, currying a function should return a function (as should partial application). Alman’s example mimics the syntax of languages like Haskell or ML where functions return a curried version if passed less than the required number of arguments. Maybe a proper name for this function is invokeOrCurry.

Performance Improvement 2:
Simply removing additional logic to always return a function result enhances curry performance. In fact, I often make “do less” the first performance enhancement of any exercise, but Crockford published first.

[Optional] Performance Improvement 3:
In cases where you will only pass simple, string/number-style arguments and you will keep the curried functions around for a while, you may want to use a memoizer to cache the functions generated. Due to the nature of test harnesses, I’ll keep this version generic.

Style Improvement 1:
With clear parameters and consistent return type, we can properly comment our new curry method and invite developers to use it:

see jsPerf tests

James Padolsey’s article on the bitwise NOT inspired me to research if the “doesn’t work for negative numbers” thing would have an easy workaround and if that workaround would allow us to still calculate faster than the Math.floor function.

I came up with this test to replace Math.floor:

//http://jsperf.com/math-floor-vs-bitwise
for (i = -10; i < 10; i += .01) {
  i > 0 ? ~~i : i == ~~i ? i : ~~i -1 === Math.floor(i) ? i : console.log("failed", i);
}

Then I came up with one for Math.round as well:

//http://jsperf.com/math-round-vs-bitwise-decimal
for (i = -5; i < 5; i += .01) {
  i > 0 ? i < ~~i + 0.5 ? ~~i : ~~i + 1 : i < ~~i - 0.5 ? ~~i - 1 : ~~i === Math.round(i) ? i : console.log("failed", i);
}

Each one will out-perform the peer Math function (your browser’s mileage may vary). See the JSPerf links (here and here);

As a colleague pointed out, if you make these expressions into a function for reuse, the Math functions will out perform them or, at worst, break even.

So, really the only time you might want to use this is in a performance-critical application (like animation). But it’s still cool!

When I look at code like the memoizer, I find things that others gloss over because of my training. My most recent project involves a huge application with brutal SLA’s. We must look at every function call or loop critically in order to achieve the required speed. That often means A/B testing in multiple browsers to see where we can shave a few milliseconds.

Here’s another example of what I’m talking about. How often do you see developers manipulate arguments in a function the way the memoizer did?

var args = Array.prototype.slice.call(arguments);

It’s pretty standard. Well, it may seem trivial, but nothing’s free. If you don’t have to do it, don’t–that’s the easiest way to boost performance. I wrote two example tests for the most common uses of arguments: iterating and prepending.

(function () {
    var i, len;
    //just iterate, you don't need an Array method (forEach is slow!)
    for (i = 0, len = arguments.length; i < len; i += 1) {
       noop(arguments[i], i);
    }
}(3, 2, 1));
 
 
var list = [3];
(function () {
    var i, len, llen;
    //we know getting length once is fast, so do it here then add them
    for (i = 0, llen = list.length, len = llen + arguments.length; i < len; i += 1) {
        //determine which set to use based on i and the length of the prepended set
        //just use property access to get arguments out, no slice, no concat
       console.log(llen > i ? list[i] : arguments[i - llen], i);
    }
}(2, 1));

get the Gist

I sent my first pull request on Github, this week.

“Welcome to two years ago,” you say.

Well, to be honest, I didn’t really understand the concept behind Github. A lot has changed in two years–I love my job.

I read Addy Osmani‘s article on the memoizer and I clicked a link. “Cool!” He wrote it up in Github. Wait, this code is different than the article. Someone made improvements?!

That got me thinking. I noticed a couple of things I could make better, so I forked the master and committed my changes. Knowing that IE7 has no native JSON support, I made the function fallback to just a no-op function. Second, I realized that there was no need to slice the arguments, you can stringify arguments and still get a unique cache key–a major performance boost. Then I made a pull request to suggest that the changes get added back to the master.

To my surprise, and delight, Jamie Mason merged my ideas. All-in-all, it was a rewarding experience and I can see myself doing it again. Social coding… who knew? I also see the value of writing code in Github then blogging it so the code conversation can continue after the article–much easier to manage than comments in a blog.