Идентичный код медленнее, чем эквивалент библиотеки закрытия JS

Я хотел создать алгоритм бинарного поиска с некоторыми модификациями. Поэтому я взял код из библиотеки закрытия Google и начал делать эти модификации. Моя модифицированная версия казалась медленнее, чем должна быть, поэтому я медленно удалил все, что, по моему мнению, могло повлиять на скорость. То, что у меня осталось, это УПРОЩЕННАЯ версия алгоритма бинарного поиска, и он все еще был в несколько раз медленнее как в Chrome, так и в Firefox. Что может быть причиной этого? Взгляните на эту тестовую страницу. Проверьте источник, чтобы понять, о чем я говорю.

https://dl.dropboxusercontent.com/s/4hhuq4biznv1jfd/SortedArrayTest.html

Это версия гугла.

goog.array.binarySearch_ = function(arr, compareFn, isEvaluator, opt_target,
    opt_selfObj) {
  var left = 0;  // inclusive
  var right = arr.length;  // exclusive
  var found;
  while (left < right) {
    var middle = (left + right) >> 1;
    var compareResult;
    if (isEvaluator) {
      compareResult = compareFn.call(opt_selfObj, arr[middle], middle, arr);
    } else {
      compareResult = compareFn(opt_target, arr[middle]);
    }
    if (compareResult > 0) {
      left = middle + 1;
    } else {
      right = middle;
      // We are looking for the lowest index so we can't return immediately.
      found = !compareResult;
    }
  }
  // left is the index if found, or the insertion point otherwise.
  // ~left is a shorthand for -left - 1.
  return found ? left : ~left;
};

Это моя версия:

        var search = function(array, num){
            var left = 0;  // inclusive
            var right = array.length;  // exclusive
            while (left < right) {
                var middle = (left + right) >> 1;
                var midValue = array[midValue];
                if (num > midValue) {
                    left = middle + 1;
                } else {
                    right = middle;
                }
            }
            return left;
        };

Поскольку люди, кажется, думают, что это что-то с функцией comparefn... когда вы не предоставляете функцию сравнения для метода binarySearch, он использует следующую функцию сравнения по умолчанию:

    goog.array.defaultCompare = function(a, b) {
      return a > b ? 1 : a < b ? -1 : 0;
    };

    goog.array.binarySearch = function(arr, target, opt_compareFn) {
  return goog.array.binarySearch_(arr,
      opt_compareFn || goog.array.defaultCompare, false /* isEvaluator */,
      target);
};

Пожалуйста, не отвечайте, не глядя на код. Догадки не очень помогают.


person user1585789    schedule 17.11.2014    source источник
comment
Попробуйте опубликовать демонстрацию JSPerf, чтобы показать разницу в производительности.   -  person elclanrs    schedule 17.11.2014
comment
Код Google получает данные из compareFn, которые он использует для установки либо влево, либо вправо, ваш код получает данные из массива, и что-то подсказывает мне, что ваш код выполняет гораздо больше итераций в цикле while. Поместите счетчик внутри цикла, чтобы увидеть, сколько раз он выполняется в каждом цикле while.   -  person adeneo    schedule 17.11.2014
comment
@adeneo compareFn просто возвращает 1 или 0 в зависимости от того, больше или меньше число среднего значения. Я просто сравниваю число со средним значением напрямую   -  person user1585789    schedule 17.11.2014
comment
Код довольно прост, и если ваша версия намного медленнее, чем версия Google, скорее всего, цикл while выполняет больше итераций, и единственный способ, которым это может произойти, — это если сравниваемые данные различаются. Вы должны отладить это как-то.   -  person adeneo    schedule 17.11.2014
comment
я предполагаю, что вызовы методов compareFn возвращают результат, который позволяет CompareResult увеличиваться влево. таким образом быстрее при возврате.   -  person james emanon    schedule 17.11.2014


Ответы (1)


Ваша реализация содержит ошибку. Это содержит:

var midValue = array[midValue]

что должно быть

var midValue = array[middle]

вместо.

По-видимому, вам не повезло, что ваш набор данных не выявил ошибку как неверный результат, а просто как проблему с производительностью.

person sjrd    schedule 17.11.2014
comment
ОМГ СПАСИБО!!! Не могу поверить, что это была такая глупая ошибка! На самом деле я никогда не проверял, что он возвращает правильные индексы! Я проверил, чтобы убедиться, что массивы отсортированы точно, но это ничего мне не сказало, потому что я даже не использовал свой алгоритм поиска для сортировки. Дох! - person user1585789; 17.11.2014