JavaScript,使用第二个参数排序更快

JavaScript,使用第二个参数排序更快,javascript,performance,sorting,Javascript,Performance,Sorting,我做了一个小测试,发现array.sort(函数(a,b){returna-b;})比array.sort()快得多在JavaScript中 结果非常令人震惊,IE9快了1.7倍,FF7快了1.6倍,Chrome快了6.7倍 另外,通过自己在JS中实现快速排序,我发现它甚至比上面提到的两种方法都要快。 (两种不同的实现,一种接受比较器函数作为参数,另一种不接受。两者都更快。) 有什么合理的解释吗 编辑:我的实现: 无比较器: function quickSort(array, from, to)

我做了一个小测试,发现
array.sort(函数(a,b){returna-b;})
array.sort()快得多在JavaScript中

结果非常令人震惊,IE9快了1.7倍,FF7快了1.6倍,Chrome快了6.7倍

另外,通过自己在JS中实现快速排序,我发现它甚至比上面提到的两种方法都要快。 (两种不同的实现,一种接受比较器函数作为参数,另一种不接受。两者都更快。)

有什么合理的解释吗

编辑:我的实现:

无比较器:

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);
}
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);
}
函数快速排序(数组、从、到){
if(typeof from===“未定义”){
from=0;
to=array.length-1;
}
else if(typeof to===‘未定义’){
to=array.length-1;
}
如果(到-从<1){
返回;
}
var i=从,枢轴=到,t;
while(i数组[pivot]){
t=数组[i];
数组[i]=数组[pivot-1];
数组[pivot-1]=数组[pivot];
数组[pivot]=t;
支点--;
}
否则{
i++;
}
}
快速排序(数组、起始、透视-1);
快速排序(数组,透视+1,到);
}
使用比较器:

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);
}
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);
}
函数quickSortFunc(数组、排序函数、从、到){
if(typeof from===“未定义”){
from=0;
to=array.length-1;
}
else if(typeof to===‘未定义’){
to=array.length-1;
}
如果(到-从<1){
返回;
}
var i=从,枢轴=到,t;
while(i0){
t=数组[i];
数组[i]=数组[pivot-1];
数组[pivot-1]=数组[pivot];
数组[pivot]=t;
支点--;
}
否则{
i++;
}
}
quickSortFunc(数组、sortfunc、from、pivot-1);
quickSortFunc(数组、排序函数、透视+1、到);
}

有两个因素起作用:

首先,正如Felix King在注释中提到的,原生排序方法在比较之前将每个数组成员转换为字符串。如果所有(或大多数)数组成员都是数字,那么使用
函数(a,b){returna-b;}
要快得多

其次,介绍了排序算法。您可能知道,也可能不知道,如果在已排序的数组中插入新元素,则快速排序的性能非常差。也许这就是WebKit决定实施选择排序的原因


但不要害怕,援助就在附近!已经有人

很多原因会起作用。不必检查变量类型是其中之一,也是唯一的一种。你的实施让乐观主义者感到高兴。它适用于密集数组,只适用于数字,变量的作用域很好,可以重用。没有this,没有with,没有eval,没有magic变量、属性、函数或类型。它将很好地优化

但是,如果您尝试实现类型独立、顺序独立的数组方法,例如
reverse()
,您可能还会发现自己的实现速度更快。至少我的是

为什么?

JavaScript现在得到了极大的优化,特别是在循环和对相同类型的东西(数字、字符串,甚至是相同形状的对象)的重复操作上。在极端情况下,运行时会内联您的函数,会跳过变量类型检查,在Chrome的情况下,甚至会将您的数字保留在注册表中,以便您的循环可以像C一样快

但这些优化只是在近几年才开始。目前,本机函数还不如用户代码那么优化。它们不像用户代码那样进行动态优化

好了,我说了

目前,用户代码可能比本机实现运行得更快,特别是因为程序员知道其中的数据流。但这可能是暂时的


我就到此为止,让您决定是否要创建自己的阵列库。;)

这是一个相当随意的猜测,但是性能会因为本机排序而受到影响,检查传递的属性是空的还是空的。。。因此,每次搜索时都会搜索默认函数(而不是一次)


这可能是一个错误的优化问题,如果正确的话可以解决。。。希望firefox开发人员能够回答这个问题:)

排序函数可能是根据平均值运行的。您使用的数组有多大?“普通”排序在元素的字符串表示上起作用。这可能是一种开销。Matt,我在100、1000、10000和100000个元素的阵列上测试了它。Felix,我对这两个问题进行了思考,它仍然没有解释为什么我使用比较器的实现比使用比较器的本机实现要快。以下是一个jsPerf作为开始:编辑:修复了一些错误(我认为)。我认为如果我们知道您的实现,给出正确的答案会有所帮助。这只是事实的一部分。请注意,大多数数组方法都有意定义为泛型,因此它们必须处理非数组的对象。如果您的实现速度更快,可能是因为您忘记了一些疯狂的特例。例如
Array.prototype.reverse.call({'2':'2','3':'3',length:'3.5',apples:'oranges'})
甚至
var a=[];a[1]=1;a、 reverse().hasOwnProperty(1)//false
。这些都是浏览器供应商不能优化的。否则jQuery将不得不处理另一个票证;)@彭彭80:刚刚检查了规格,但是没有看到这个例子有什么极端之处。规范要求取长度,设为unsigned int,然后开始从0反转为length-1。我可以知道这里的陷阱是什么吗?我还没有看到您的实现,但肯定是较慢的。