Почему вторая операция быстрее первой? - PullRequest
2 голосов
/ 30 апреля 2019

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

process.env.UV_THREADPOOL_SIZE = 1;

let array = [
  1,
  23,
  4,
  5,
  6,
  7,
  8,
  7,
  65,
  4,
  3,
  23,
  43,
  2,
  23,
  32,
  23,
  23,
  234,
  243,
  423,
  432,
  43,
  23,
  2,
  23,
  2,
  23,
];

let sum = 0;
console.time('reduce');
sum = array.reduce((s, p) => (s += p), 0);
console.timeEnd('reduce');

sum = 0;
console.time('for');
for (let i = 0; i < array.length; i++) {
  sum += array[i];
}
console.timeEnd('for');

И этот код показывает разные результаты:

process.env.UV_THREADPOOL_SIZE = 1;

let array = [
  1,
  23,
  4,
  5,
  6,
  7,
  8,
  7,
  65,
  4,
  3,
  23,
  43,
  2,
  23,
  32,
  23,
  23,
  234,
  243,
  423,
  432,
  43,
  23,
  2,
  23,
  2,
  23,
];

let sum = 0;
console.time('for');
for (let i = 0; i < array.length; i++) {
  sum += array[i];
}
console.timeEnd('for');

sum = 0;
console.time('reduce');
sum = array.reduce((s, p) => (s += p), 0);
console.timeEnd('reduce');

Я имею в виду, если вы измените порядок выполнения, результаты измерений будут другими.

Для проведения теста я использую узел v11.11.0

Есть идеи по этому поводу?

РЕДАКТИРОВАТЬ: я не ищу объяснение, почему сокращение быстрее, чем для или что-то вродетот.Я хочу знать, почему nodejs производит это в результате этой последовательности операций.

Ответы [ 5 ]

2 голосов
/ 30 апреля 2019

Я имею в виду, если вы измените порядок выполнения, результаты измерений будут другими.

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

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

До этого нельзя судить, один из них быстрее. Результат, скорее всего, будет следующим: это не имеет значения, оба достаточно быстры.

Стоит прочитать: Что быстрее? - Эрик Липперт

1 голос
/ 02 мая 2019

После тестирования обоих нет большой разницы во времени между ними.

В ссылке вы можете проверить ее, изменив количество выполнений.

https://repl.it/@statefull/TrustworthyDefiniteArraylist

После некоторых тестов проблема в функции console.time.

Смотрите это:

https://repl.it/@statefull/WrathfulCostlyIrc

Первый раз, когда вызывается * 1016, это занимает больше времени. Сравнивается с Date.now для каждого выполнения.

Еще несколько тестов показывают, что до первого console.timeEnd измерение времени первого console.timeEnd не является реальным.

См: https://repl.it/@statefull/SoggyLimegreenUser

0 голосов
/ 30 апреля 2019

Это обычное явление в скриптовых или JIT-скомпилированных языках, и оно связано с накладными расходами компилятора, замедляющими вашу работу, но только в первый раз. После этого первого раза вы вызываете скомпилированный код, а не компилируете скрипт, хотя это зависит от того, как реализован механизм исполнения. Вот почему тестирование обычно требует, чтобы вы что-то делали не один раз, а несколько (в идеале) тысяч раз

0 голосов
/ 30 апреля 2019

Map / Reduce / Filter / Find работают медленно, потому что у них есть функции обратного вызова, это добавляет издержки

0 голосов
/ 30 апреля 2019

Вы добавляете функцию в стек для каждой итерации Reduce (() => {} - это новый вызов функции).Эти вызовы функций добавляют немного дополнительного времени к общему процессу.

Пока ограничения по времени не очень строги или массивы очень велики, увеличение читабельности обычно того стоит.

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