JavaScript, сортировка по второму параметру быстрее - PullRequest
18 голосов
/ 28 августа 2011

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

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

Кроме того, реализовав саму быструю сортировку в 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);
}

Ответы [ 3 ]

1 голос
/ 28 августа 2011

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

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

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

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

0 голосов
/ 31 августа 2011

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

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

0 голосов
/ 28 августа 2011

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

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

Почему?

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

Wow.

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...