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

Revision 63 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/

Preparation HTML

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>

Setup

var _isFirefox= /Firefox/i.test(navigator.userAgent);
    var _arr = [];
    var n = 100;
    while (n--) {
        var text = "";
        var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    
        for( var i=0; i < 100; i++ ){
            text += possible.charAt(Math.floor(Math.random() * possible.length));
        }
        _arr.push(text);
    }
    
    function adaptiveArrayReverse(_array){
        var _tempArray = _array.slice(0);
        var _length = _tempArray.length,
            _left = null,
            _right = null,
            _temporary;
        
        if (_isFirefox){
            for (_left = 0; _left < _length / 2; _left += 1) {
                _right = _length - 1 - _left;
                _temporary = _tempArray[_left];
                _tempArray[_left] = _tempArray[_right];
                _tempArray[_right] = _tempArray;
            }
        } else {
            for (_left = 0, _right = _length - 1; _left < _right; _left += 1, _right -= 1){
                _temporary = _tempArray[_left];
                _tempArray[_left] = _tempArray[_right];
                _tempArray[_right] = _temporary;
            }
        }
        
        _length = null,
        _left=null,
        _right = null,
        _temporary = null,
        _array = null;
        
        return _tempArray;
    }
    function adaptiveArrayReverse2(_array){
        var _length = _array.length,
            _left = null,
            _right = null;
        var _tempArray = Array.apply(null, Array(_length)).map(function () {});
        
        if (_isFirefox){
            for (_left = 0; _left < _length / 2; _left += 1) {
                _right = _length - 1 - _left;
                _tempArray[_left] = _array[_right];
                _tempArray[_right] = _array[_left];
            }
        } else {
            for (_left = 0, _right = _length - 1; _left < _right; _left += 1, _right -= 1){
                _tempArray[_left] = _array[_right];
                _tempArray[_right] = _array[_left];
            }
        }
        if (!Number.isInteger(_length / 2)){
            var _nonCopiedElementPos = Math.floor(_length / 2);
            _tempArray[_nonCopiedElementPos] = _array[_nonCopiedElementPos];
    
            _nonCopiedElementPos = null;
        }
        
        _length = null,
        _left=null,
        _right = null,
        _temporary = null,
        _array = null;
        
        return _tempArray;
    }
    
    function arrReverse(array){
        var _tempArray = array.slice(0);
        return _tempArray.reverse();
    }  
    
    function forSwap(array){
        var _tempArray = array.slice(0);
        
        var length = _tempArray.length,
            left = null,
            right = null,
            temporary;
            
        for (left = 0, right = length - 1; left < right; left += 1, right -= 1) {
            temporary = _tempArray[left];
            _tempArray[left] = _tempArray[right];
            _tempArray[right] = temporary;
        }
        
        length = null,
        left=null,
        right = null,
        temporary = null,
        _array = null;
        
        return _tempArray;
    }
    
    function forSwapHalf(array){
        var _tempArray = array.slice(0);
        
        var length = _tempArray.length,
            left = null,
            right = null,
            temporary;
            
        for (left = 0; left < length / 2; left += 1) {
            right = length - 1 - left;
            temporary = _tempArray[left];
            _tempArray[left] = _tempArray[right];
            _tempArray[right] = temporary;
        }
        
        length = null,
        left=null,
        right = null,
        temporary = null,
        _array = null;
        
        return _tempArray;
    }

Test runner

Ready to run.

Testing in
TestOps/sec
Array.reverse()
result = arrReverse(_arr);
ready
Adaptive Array Reverse
result = adaptiveArrayReverse(_arr);
ready
For Swap
result = forSwap(_arr);
ready
For Swap Half
result = forSwapHalf(_arr);
ready
Adaptive Array Reverse without array cloning
result = adaptiveArrayReverse2(_arr);
ready
Destructive array.revese()
result = _arr.reverse()
ready

Revisions

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