Подтвердить что ты не робот

JavaScript, сортировка со вторым параметром выполняется быстрее

Я сделал небольшой тест и выяснил, что array.sort(function(a, b) { return a - b; }); намного быстрее, чем array.sort(); в JavaScript.

Результаты были довольно шокирующими, примерно в 1,7 раза быстрее в IE9, 1,6 раза в FF7 и в 6,7 раз в Chrome.

Кроме того, реализовав quicksort самостоятельно в JS, я обнаружил, что он был даже быстрее, чем оба упомянутых выше метода. (Две разные реализации, одна принимает функцию сравнения как параметр, другая - нет. Оба были быстрее.)

Есть ли разумное объяснение?

EDIT: мои реализации:

Нет сравнения:

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);
}
4b9b3361

Ответ 1

Вступают в игру два фактора:

Во-первых, как упоминал в комментариях Феликс Кинг, собственный метод сортировки преобразует каждый элемент массива в строку перед сравнением. Использование function(a, b) { return a - b; } выполняется быстрее, если все (или большинство) элементов массива являются числами.

Во-вторых, алгоритм сортировки зависит от реализации. Как вы можете или не знаете, quicksort выполняет очень плохо, если вы вставляете новый элемент в уже отсортированный массив. Возможно, поэтому WebKit решил реализовать Selection Sort вместо.

Но не бойся, помощь рядом! Кто-то уже разветвленный WebKit, чтобы исправить это

Ответ 2

В игру придут многие причины. Не обязательно проверять тип переменной - это один из них и только один из них. И ваша реализация делает оптимизатора счастливым. Он работает с плотным массивом, он работает только с числами, переменные хорошо охвачены и используются повторно. Нет, нет, нет, нет eval, нет волшебных переменных, свойств, функций или типов. Он будет хорошо оптимизирован.

Однако, если вы попытались реализовать методы типа-idependent, не зависящие от порядка, такие как reverse(), вы также можете обнаружить, что ваша собственная реализация выполняется быстрее. По крайней мере моя есть.

Почему?

JavaScript в настоящее время сильно оптимизирован, особенно на циклах и повторных операциях на одном и том же носителе - число, строка, даже объекты одинаковой формы (это сложно). В крайних случаях среда выполнения включала ваши функции, пропускала проверки типов переменных и, в случае Chrome, даже сохраняла бы ваши номера в реестрах, чтобы ваш цикл мог быть таким же быстрым, как C.

Ого.

Но эти оптимизации только в последнее время проявились. В настоящий момент нативные функции еще не так оптимизированы, как пользовательский код. Они не претерпевают столько динамических оптимизаций, сколько пользовательский код.

Там я это сказал.

В настоящее время код пользователя может работать быстрее, чем встроенная реализация, особенно, поскольку программист знает, какие данные в нем поступают. Но это может быть временным.

Я остановлюсь здесь и позволю вам решить, хотите ли вы создать свою собственную библиотеку массивов.;)

Ответ 3

Это довольно дикая догадка, но может произойти поражение производительности из-за родной сортировки, проверка того, прошли ли атрибуты пустые или нулевые... Следовательно, поиск функции по умолчанию для каждого поиска (а не один раз)...

Это может быть ошибочная проблема оптимизации, которая может быть решена, если это правда... Надеюсь, кто-то из разработчиков firefox может ответить на этот вопрос.