JS: Array.reverse() vs. for and while loops (v60)

Revision 60 of this benchmark created on


Description

Checking performance of Array.reverse() vs custom loops.

See http://stackoverflow.com/questions/5276953/what-is-the-most-efficient-way-to-reverse-an-array-in-javascript.

Also see http://jsperf.com/forloop-vs-reverse-while-loop-and-array-reverse/9.

Edited to make sure JIT isn't being "smart" and doing some extra optimizations that won't exist on real applications, also increased the number of items to 1000 to represent a common scenario (perf usually changes drastically based on amount of items, some techniques might only be fast for a short amount of items). See: http://blog.millermedeiros.com/benchmarking-is-hard/

Setup

// at least 1K items to make sure it's fast, performnace usually changes
    // based on the amount of items
    var array = [];
    var n = 100;
    while (n--) {
      array.push(n * Math.random());
    }
    
    // we store result outside of test scope to make sure JIT isn't simply ignoring
    // the operations on some cases
    var result;
    
    
    // implementations
    // ---------------
    // note that the behavior isn't the same on all methods, some are "destructive"
    // while others returns a new Array. It's like comparing apples to oranges.
    
    
    function arrReverse(array){
      return array.reverse();
    }
    
    
    function pushSlice(array){
      var left = 0;
      var length = array.length;
      while (left < length) {
        array.push(array[length - 1 - ++left]);
        array.splice(length - 1 - left, 1);
      }
      return array;
    }
    
    
    function whileForward(array){
      var left = 0;
      var length = array.length;
      while (left < length) {
        var right = length - 1 - left;
        array.push(array[right]);
        array.splice(right, 1);
        left += 1;
      }
      return array;
    }
    
    
    function forThenSlice(array){
      var length = array.length;
      for (length -= 2; length > -1; length -= 1) {
        array.push(array[length]);
        array.splice(length, 1);
      }
      return array;
    }
    
    
    function forPush(array){
      var length = array.length;
      var result = [];
      var i = null;
      for (i = length - 1; i >= 0; i -= 1) {
        result.push(array[i]);
      }
      return result;
    }
    
    
    function forSwap(array){
      var length = array.length;
      var left = null;
      var right = null;
      for (left = 0, right = length - 1; left < right; left += 1, right -= 1) {
          var temporary = array[left];
          array[left] = array[right];
          array[right] = temporary;
      }
      return array;
    }
    
    
    function forSwapHalf(array){
      var length = array.length;
      var left = null;
      var right = null;
      for (left = 0; left < length / 2; left += 1) {
        right = length - 1 - left;
        var temporary = array[left];
        array[left] = array[right];
        array[right] = temporary;
      }
      return array;
    }
    
    
    function xorSwap(array){
      var length = array.length;
      var i = null;
      var r = null;
      for (i = 0, r = length - 1; i < r; i += 1, r -= 1) {
        var left = array[i];
        var right = array[r];
        left ^= right;
        right ^= left;
        left ^= right;
        array[i] = left;
        array[r] = right;
      }
      return array;
    }
    
    function xorSwapHalf(array){
      var length = array.length;
      var i = null;
      var r = null;
      for (i = 0; i < length / 2; i += 1) {
        r = length - 1 - i;
        var left = array[i];
        var right = array[r];
        left ^= right;
        right ^= left;
        left ^= right;
        array[i] = left;
        array[r] = right;
      }
      return array;
    }
    
    
    function forSwapHalfNonDestructive(arr) {
      var results = [];
      for (var i = 0, j = arr.length, k; i < j / 2; i += 1) {
        k = j - 1 - i;
        results[i] = arr[k];
        results[k] = arr[i];
      }
      return results;
    }

Test runner

Ready to run.

Testing in
TestOps/sec
Array.reverse()
result = arrReverse(array);
ready
while push then slice
result = pushSlice(array);
ready
while forward
result = whileForward(array);
ready
for push then slice
result = forThenSlice(array);
ready
for push
result = forPush(array);
ready
for swap
result = forSwap(array);
ready
for swap half
result = forSwapHalf(array);
ready
XOR swap
result = xorSwap(array);
ready
XOR swap half
result = xorSwapHalf(array);
ready
for swap half non-destructive
result = forSwapHalfNonDestructive(array);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.