最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

performance - JavaScript, sorting with second parameter is faster - Stack Overflow

programmeradmin4浏览0评论

I have made a little test, and found out that array.sort(function(a, b) { return a - b; }); is a lot faster than array.sort(); in JavaScript.

The results were quite shocking, about 1.7 times faster in IE9, 1.6 times in FF7 and 6.7 times in Chrome.

Also, by implementing quicksort by myself in JS, I found it was even faster than both methods mentioned above. (Two different implementations, one accepts a parer function as a parameter, the other doesn't. Both were faster.)

Is there any reasonable explanation?

EDIT: My implementations:

No parer:

function quickSort(array, from, to) {
    if(typeof from === 'undefined') {
        from = 0;
        to = array.length - 1;
    }
    else if(typeof to === 'undefined') {
        to = array.length - 1;
    }

    if(to - from < 1) {
        return;
    }

    var i = from, pivot = to, t;

    while(i < pivot) {
        if(array[i] > array[pivot]) {
            t = array[i];
            array[i] = array[pivot - 1];
            array[pivot - 1] = array[pivot];
            array[pivot] = t;
            pivot--;
        }
        else {
            i++;
        }
    }

    quickSort(array, from, pivot - 1);
    quickSort(array, pivot + 1, to);
}

With parer:

function quickSortFunc(array, sortfunc, from, to) {
    if(typeof from === 'undefined') {
        from = 0;
        to = array.length - 1;
    }
    else if(typeof to === 'undefined') {
        to = array.length - 1;
    }

    if(to - from < 1) {
        return;
    }

    var i = from, pivot = to, t;

    while(i < pivot) {
        if(sortfunc(array[i], array[pivot]) > 0) {
            t = array[i];
            array[i] = array[pivot - 1];
            array[pivot - 1] = array[pivot];
            array[pivot] = t;
            pivot--;
        }
        else {
            i++;
        }
    }

    quickSortFunc(array, sortfunc, from, pivot - 1);
    quickSortFunc(array, sortfunc, pivot + 1, to);
}

I have made a little test, and found out that array.sort(function(a, b) { return a - b; }); is a lot faster than array.sort(); in JavaScript.

The results were quite shocking, about 1.7 times faster in IE9, 1.6 times in FF7 and 6.7 times in Chrome.

Also, by implementing quicksort by myself in JS, I found it was even faster than both methods mentioned above. (Two different implementations, one accepts a parer function as a parameter, the other doesn't. Both were faster.)

Is there any reasonable explanation?

EDIT: My implementations:

No parer:

function quickSort(array, from, to) {
    if(typeof from === 'undefined') {
        from = 0;
        to = array.length - 1;
    }
    else if(typeof to === 'undefined') {
        to = array.length - 1;
    }

    if(to - from < 1) {
        return;
    }

    var i = from, pivot = to, t;

    while(i < pivot) {
        if(array[i] > array[pivot]) {
            t = array[i];
            array[i] = array[pivot - 1];
            array[pivot - 1] = array[pivot];
            array[pivot] = t;
            pivot--;
        }
        else {
            i++;
        }
    }

    quickSort(array, from, pivot - 1);
    quickSort(array, pivot + 1, to);
}

With parer:

function quickSortFunc(array, sortfunc, from, to) {
    if(typeof from === 'undefined') {
        from = 0;
        to = array.length - 1;
    }
    else if(typeof to === 'undefined') {
        to = array.length - 1;
    }

    if(to - from < 1) {
        return;
    }

    var i = from, pivot = to, t;

    while(i < pivot) {
        if(sortfunc(array[i], array[pivot]) > 0) {
            t = array[i];
            array[i] = array[pivot - 1];
            array[pivot - 1] = array[pivot];
            array[pivot] = t;
            pivot--;
        }
        else {
            i++;
        }
    }

    quickSortFunc(array, sortfunc, from, pivot - 1);
    quickSortFunc(array, sortfunc, pivot + 1, to);
}
Share Improve this question edited Jul 15, 2013 at 12:28 holographic-principle 19.7k10 gold badges48 silver badges62 bronze badges asked Aug 28, 2011 at 12:51 Shay Ben-MosheShay Ben-Moshe 1,2963 gold badges12 silver badges27 bronze badges 8
  • It's a possibility that the sort function is run from averages. How big were the arrays that you used? – Matt Commented Aug 28, 2011 at 12:53
  • 3 "Normal" sort works on the string representation of the elements. That could be a possible overhead. – Felix Kling Commented Aug 28, 2011 at 12:54
  • Matt, I tested it on arrays of 100, 1000, 10000 and 100000 elements. Felix, I though about that two, it still doesn't explain why my implementation with a parer was faster than the native implementation with a parer. – Shay Ben-Moshe Commented Aug 28, 2011 at 12:57
  • 2 Here is a jsPerf as a start: jsperf./sort-parison Edit: Fixed some errors (I think). – Felix Kling Commented Aug 28, 2011 at 12:59
  • I think to give a proper answer it would help if we knew your implementation. – Felix Kling Commented Aug 28, 2011 at 13:09
 |  Show 3 more ments

3 Answers 3

Reset to default 1

There's two factors that e into play:

First, as Felix King mentioned in the ments, the native sort method converts each array member to a string before paring. Using function(a, b) { return a - b; } is way faster if all (or most) array members are numbers.

Second, the sorting algorithm is implementation dependent. As you may or may not know, quicksort performs really bad if you insert a new element into an already sorted array. Maybe that's why WebKit decided to implement Selection Sort instead.

But fear not, help is near! Somebody already forked WebKit to fix this

Many reasons would e into play. Not having to check variable type is one of them and only one of them. And your implementation makes the optimiser happy. It works with dense array, it works only with numbers, the variables are well scoped and reused. No this, no with, no eval, no magic variables, properties, functions, or types. It would optimise well.

However, if you have tried to implement type-idependent, order-independent array methods such as reverse() you may also find that your own implementation is faster. At least mine is.

Why?

JavaScript is heavily optimised nowadays, espcially on loops and repeated operations on same type of stuffs - number, string, even objects of same shape (it's plicated). In extreme cases the runtime would inline your functions, would skip variable type checks, and, in case of Chrome, would even keep your numbers in registries so that your loop can be as fast as C.

Wow.

But these optimisations only took off in recent years. At this moment, native functions are not yet as optimisable as user code. They don't undergo as much dynamic optimisations as user code do.

There, I said it.

Currently, user code may run faster then native implementation, espcially since the programmer knows what data flow in it. But this can be temporary.

I'll stop here and let you decide whether you want to create your own array library. ;)

This is quite a wild guess, but could the performance hit occur due to the native sort, checking if the attributes passed is blank or null... Hence searching up the default function on each search (instead of once)...

It could be a mistaken optimization issue, that could be resolved if true... Hopefully someone in firefox dev can answer this :)

发布评论

评论列表(0)

  1. 暂无评论