jsPerf.app is an online JavaScript performance benchmark test runner & jsperf.com mirror. It is a complete rewrite in homage to the once excellent jsperf.com now with hopefully a more modern & maintainable codebase.
jsperf.com URLs are mirrored at the same path, e.g:
https://jsperf.com/negative-modulo/2
Can be accessed at:
https://jsperf.app/negative-modulo/2
[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.
<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>
// 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);
}
Ready to run.
Test | Ops/sec | |
---|---|---|
1A: Array len: *10* -- Cached Array.proto.reverse |
| ready |
1B: Array len: *10* -- Func wrapping simple for-loop val-swap |
| ready |
1C: Array len: *10* -- Func wrapping to-spec for-loop val-swap |
| ready |
1D: Array len: *10* -- Func wrapping cached Array.proto.reverse + call() |
| ready |
1E: Array len: *10* -- Bound Func.call() on Array.proto.reverse |
| ready |
2A: Array len: *50* -- Cached Array.proto.reverse |
| ready |
2B: Array len: *50* -- Func wrapping simple for-loop val-swap |
| ready |
2C: Array len: *50* -- Func wrapping to-spec for-loop val-swap |
| ready |
2D: Array len: *50* -- Func wrapping cached Array.proto.reverse + call() |
| ready |
2E: Array len: *50* -- Bound Func.call() on Array.proto.reverse |
| ready |
3A: Array len: *250* -- Cached Array.proto.reverse |
| ready |
3B: Array len: *250* -- Func wrapping simple for-loop val-swap |
| ready |
3C: Array len: *250* -- Func wrapping to-spec for-loop val-swap |
| ready |
3D: Array len: *250* -- Func wrapping cached Array.proto.reverse + call() |
| ready |
3E: Array len: *250* -- Bound Func.call() on Array.proto.reverse |
| ready |
You can edit these tests or add more tests to this page by appending /edit to the URL.