@thsiganenko
Пользователь электрического примуса

Правильно ли проведено тестирование работы функции реверса массива на JavaScript?

Доброго времени суток, уважаемые участники сообщества!

В книге Марейна Хавербека "Выразительный JavaScript" в качестве упражнения предложено написать функцию реверса массива, то есть нужно взять массив и перевернуть его, чтобы элементы, которые были в начале оказались в конце. Есть стандартный метод у массивов .reverse(), который выполняет эту функцию.
Данная задачу уже упоминалась среди вопросов, и был предложен ряд интересных решений.

Для тренировки решил задачу несколькими способами и решил проверить, сколько времени занимает каждый вариант.
Мной было реализовано 4 функции.

Первый вариант с помощью цикла While:
function reversInPlaceWhile(arr) {
    var len = arr.length - 1;
    var i = 0, temp;
    while (i < len - i) {
        temp = arr[i];
        arr[i] = arr[len - i];
        arr[len - i] = temp;
        i++;
    }
    return arr;
}


Второй вариант с помощью цикла For
function reversInPlaceFor(arr) {
    var len = arr.length - 1;
    var temp;
    for (var i = 0, iter = Math.floor(len / 2); i < iter; i++) {
        temp = arr[i];
        arr[i] = arr[len - i];
        arr[len - i] = temp;
    }
    return arr;
}


Вариант третий, с использование стандартного метода:
function reversInPlaceStandart(arr) {
    arr.reverse();
    return arr;
}


Вариант четвертый, с помощью метода splice()
(этот вариант был предложен одним из участников сообщества)
function reversInPlaceSplice(arr) {
    var len = arr.length - 1;
    for (var i = 0; i < len; i++) {
        arr.splice(i, 0, arr.pop());
    }
    return arr;
}


Для целей тестирования создал функцию, генерирующую простой массив нужного размера:
function newArrayLine(count) {
    var arr = [];
    for (var i = 0; i < count; i++) {
        arr[i] = i;
    }
    return arr;
}


И наконец, для целей тестирования, я использовал функцию:
function test(arr, iter, callback) {
    var start = Date.now();
    for (var i = 0; i < iter; i++) {
        callback(arr);
    }
    var end = Date.now();
    return end - start;
}

где arr - это массив, который будет переворачивать
iter - количество раз, которые нужно переворачивать
callback - функция, с помощью которой будем переворачивать массив
Результат я ожидал получить в миллисекундах.

Запуская данную функцию на массиве 10 000 элементов, 100 раз, в браузере Mozilla Firefox, получил следующие результаты:
для функции с циклом while: 1 мс;
для функции с циклом for: 1 мс;
для функции с стандартным методом reverse(): 12 мс;
для функции с методом splice(): 6562 мс;

Запуская данную функцию на массиве 100 000 элементов, 100 раз, в браузере Chome, получил следующие результаты:
для функции с циклом while: 7 мс;
для функции с циклом for: 6 мс;
для функции с стандартным методом reverse(): 25 мс;
для функции с методом splice(): 485163 мс;

Запускал функции несколько раз, результаты примерно одинаковы.
Удивительно то, что встроенный метод работает медленнее, чем реализованные с циклами.

А теперь собственно основной вопрос: правильно ли проведено тестирование, и можно ли считать данные репрезентативными?

И еще один вопрос, нет ли в моем коде, каких-либо ошибок или недочетов, на которые мне следовало бы обратить внимание?

Заранее благодарен тем, кто решил уделить время моему вопросу!
  • Вопрос задан
  • 686 просмотров
Пригласить эксперта
Ответы на вопрос 2
alexey-m-ukolov
@alexey-m-ukolov Куратор тега JavaScript
@thsiganenko Автор вопроса
Пользователь электрического примуса
copal А если таким образом. Хотя меня что-то сильно смущает такой подход, но все же спрошу.

Создаем объект reversArray и у него три метода с различными реализациями реверса массива.
Далее вызываем с помощью кода:
function testOne() {
    var start = Date.now();
    reversArray.reversInPlaceWhile(newArrayLine(100000));
    var end = Date.now();
    return end - start;
}


А для нативной функции используем следующий код:
function testTwo() {
    var start = Date.now();
    newArrayLine(100000).reverse();
    var end = Date.now();
    return end - start;
}


Такое чувство, что я начал путать "теплое" с "мягким", не могу только понять где ошибка.
Работать работает, результат уже не сильно отличается по скорости работы, все же нативный метод при таком подходе дает большее время выполнения.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы