Various arrays: Array.proto.reverse() vs. wrapped / bound versions vs. func-wrapped swap-loop and to-spec swap-loop (v59)

Revision 59 of this benchmark created by SirShanus on


Description

[1] Cached [].reverse.call vs. generic util funcs wrapping [2] a simple loop val-swap approach and [3] the same loop approach but extended to be fully to-ES-spec. [2] is faster than [1] in many cases, BUT it ignores holes. Is [2] still a winner when made fully compliant, as [3]?

So as to also check effects of similarly styled [].reverse util-func variants, which require no additional object method-lookups on invocation (e.g. to facilitate a programmatically-constructed {namespace}[method-name](arg)-type call), we'll throw in: [4] a func-wrapper for [].reverse.call and [5] a bound version.

Preparation HTML

<script>
var   tArr1 = ['aa','bb','cc','dd','ee','ff','ww','xx','yy','zz'],
      tArr2 = tArr1.concat(tArr1, tArr1, tArr1, tArr1),   // len:50
      tArr3 = tArr2.concat(tArr2, tArr2, tArr2, tArr2),   // len:250
      tArr1,   tArr2,   tArr3,
      arrReverse,   wrappedArrReverse,   boundArrReverse;

// deletes arr[ 2, 5, 8... ]
function makeHoles(_, idx, self){
  if (   !( (idx + 1) % 3 )   ) {   delete self[idx];   }
}
tArr1.forEach(makeHoles),   tArr2.forEach(makeHoles),
    tArr3.forEach(makeHoles);

function restoreHoles(val, idx, self){
  if ( val === void(0) ) {   delete self[idx];   }
}


function swapLoopArrReverse(arr) {   "use strict";
  for ( var i = 0, j = (arr.length - 1), tmp; i < j; i++, j-- ) {
    tmp = arr[i],   arr[i] = arr[j],   arr[j] = tmp;
  }
  return arr;
}

function swapLoopArrReverse_spec(arr) {   "use strict";
  var   UNDEF = void(0),   tmp1,   tmp2;
  for ( var i = 0, j = (arr.length - 1); i < j; i++, j-- ) {
    if (   ( tmp1 = arr[i] ) === UNDEF && !(i in arr)   ) {
      if (   ( tmp2 = arr[j] ) !== UNDEF || j in arr   ) {
        arr[i] = tmp2,   delete arr[j];
      } else {   continue;   }
    } else if (   ( tmp2 = arr[j] ) === UNDEF && !(j in arr)   ) {
      arr[j] = tmp1,   delete arr[i];
    } else {   arr[j] = tmp1,   arr[i] = tmp2;   }
  }
  return arr;
}

~(function(){   "use strict";
  var   _arrReverse =   arrReverse =   [].reverse;

  wrappedArrReverse = function wrappedArrReverse(arr) {
    return _arrReverse.call(arr);
  };
  boundArrReverse = _arrReverse.call.bind(_arrReverse);
})();

</script>

Setup

// Since `[].forEach` skips holes, these would be no-ops for all 
    // test cases besides TC [2]
    if (0 in tArr1 && 1 in tArr1 && 2 in tArr1) {
      tArr1.forEach(restoreHoles);
    }
    else if (0 in tArr2 && 1 in tArr2 && 2 in tArr2) {
      tArr2.forEach(restoreHoles);
    }
    else if (0 in tArr3 && 1 in tArr3 && 2 in tArr3) {
      tArr3.forEach(restoreHoles);
    }

Test runner

Ready to run.

Testing in
TestOps/sec
1A: Array len: *10* -- Cached Array.proto.reverse
arrReverse.call(tArr1);
 
ready
1B: Array len: *10* -- Func wrapping simple for-loop val-swap
swapLoopArrReverse(tArr1);
ready
1C: Array len: *10* -- Func wrapping to-spec for-loop val-swap
swapLoopArrReverse_spec(tArr1);
ready
1D: Array len: *10* -- Func wrapping cached Array.proto.reverse + call()
wrappedArrReverse(tArr1);
ready
1E: Array len: *10* -- Bound Func.call() on Array.proto.reverse
boundArrReverse(tArr1);
ready
2A: Array len: *50* -- Cached Array.proto.reverse
arrReverse.call(tArr2);
 
ready
2B: Array len: *50* -- Func wrapping simple for-loop val-swap
swapLoopArrReverse(tArr2);
 
ready
2C: Array len: *50* -- Func wrapping to-spec for-loop val-swap
swapLoopArrReverse_spec(tArr2);
 
ready
2D: Array len: *50* -- Func wrapping cached Array.proto.reverse + call()
wrappedArrReverse(tArr2);
 
ready
2E: Array len: *50* -- Bound Func.call() on Array.proto.reverse
boundArrReverse(tArr2);
ready
3A: Array len: *250* -- Cached Array.proto.reverse
arrReverse.call(tArr3);
 
ready
3B: Array len: *250* -- Func wrapping simple for-loop val-swap
swapLoopArrReverse(tArr3);
 
ready
3C: Array len: *250* -- Func wrapping to-spec for-loop val-swap
swapLoopArrReverse_spec(tArr3);
 
ready
3D: Array len: *250* -- Func wrapping cached Array.proto.reverse + call()
wrappedArrReverse(tArr3);
 
ready
3E: Array len: *250* -- Bound Func.call() on Array.proto.reverse
boundArrReverse(tArr3);
ready

Revisions

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