Size: a a a

JavaScript.Ninja

2020 August 06

T

Tim in JavaScript.Ninja
Michael
Чуваки, вот на собесе СТО спросил "как ты верстаешь?". Какой ответ он ожидал?
Семантично, адаптивно, как скажут
источник

T

Tim in JavaScript.Ninja
.
народ, можете подсказать что вы используете для сжатия картинок на бэке
gulp-imagemin
источник

DP

Den Pol in JavaScript.Ninja
Почему первый способ намного быстрее?

function fib(n) {
 // V1: LIGHT
 // const result = [];
 // eslint-disable-next-line no-plusplus
 // for (let i = 0; i < n; i++) {
 //   if (i === 0 || i === 1) {
 //     result.push(1);
 //   } else {
 //     result.push(result[i - 1] + result[i - 2]);
 //   }
 // }
 // return result[n - 1];

 // V2: HARD
 const arr = new Array(n);
 // eslint-disable-next-line no-plusplus
 for (let i = 0, max = arr.length; i < max; i++) {
   if (i === 0 || i === 1) {
     arr[i] = 1;
   } else {
     arr[i] = arr[i - 1] + arr[i - 2];
   }
 }

 return arr[n - 1];
}

console.time("fib(77)");
console.log(fib(77));
console.timeEnd("fib(77)");

// LIGHT:
// Output: "fib(77): 0.165ms"

// HARD:
// Output: "fib(77): 7.580ms"
источник

DP

Den Pol in JavaScript.Ninja
источник

M

Misha in JavaScript.Ninja
Den Pol
Почему первый способ намного быстрее?

function fib(n) {
 // V1: LIGHT
 // const result = [];
 // eslint-disable-next-line no-plusplus
 // for (let i = 0; i < n; i++) {
 //   if (i === 0 || i === 1) {
 //     result.push(1);
 //   } else {
 //     result.push(result[i - 1] + result[i - 2]);
 //   }
 // }
 // return result[n - 1];

 // V2: HARD
 const arr = new Array(n);
 // eslint-disable-next-line no-plusplus
 for (let i = 0, max = arr.length; i < max; i++) {
   if (i === 0 || i === 1) {
     arr[i] = 1;
   } else {
     arr[i] = arr[i - 1] + arr[i - 2];
   }
 }

 return arr[n - 1];
}

console.time("fib(77)");
console.log(fib(77));
console.timeEnd("fib(77)");

// LIGHT:
// Output: "fib(77): 0.165ms"

// HARD:
// Output: "fib(77): 7.580ms"
Больше работы с памятью?
источник

IK

Illya Klymov in JavaScript.Ninja
Сферический тест в вакууме
источник

IK

Illya Klymov in JavaScript.Ninja
Массив с фиксированным размером убивает оптимизации хрома
источник

IK

Illya Klymov in JavaScript.Ninja
Обращение к длине массива ненужное
источник

DP

Den Pol in JavaScript.Ninja
Illya Klymov
Обращение к длине массива ненужное
Если не завести переменную max - дина будет вычисляться на каждой итерации (+200 ms).
источник

DP

Den Pol in JavaScript.Ninja
Задача, кстати, от яндекса.

/*
# Числа Фибоначчи

Последовательность [чисел Фибоначчи](https://ru.wikipedia.org/wiki/Числа_Фибоначчи)
определяется формулой F(n) = F(n-1) + F(n-2).
То есть, следующее число получается как сумма двух предыдущих.

Первые два числа равны 1, затем 2(1+1), затем 3(1+2), 5(2+3)
и так далее: 1, 1, 2, 3, 5, 8, 13, 21....

Напишите функцию fib(n) которая возвращает n-е число Фибоначчи.

Пример работы:

fib(3); // 2
fib(7); // 13
fib(77); // 5527939700884757

P.S. Все запуски функций из примера выше должны работать быстро.
Вызов fib(77) должен занимать не более доли секунды.
*/
источник

IK

Illya Klymov in JavaScript.Ninja
И что?
источник

AC

Alexander Chernobai in JavaScript.Ninja
рекурсия?
источник

AC

Alexander Chernobai in JavaScript.Ninja
)
источник

AC

Alexander Chernobai in JavaScript.Ninja
или редьюс
источник

SK

Sergey Kostyrko in JavaScript.Ninja
там кстати можно без массива несколькими переменными обойтись - скорее всего будет бвстрее
но вообще по поводу таких бенчмарков есть отличный доклад - https://www.youtube.com/watch?v=g0ek4vV7nEA&t=728s
long story short - никогда не знаешь что с твоим кодом станет при компиляции/оптимизации поэтому такие микро бенчмарки ни о чем
источник

MP

Maxim Pismenskiy in JavaScript.Ninja
Den Pol
Задача, кстати, от яндекса.

/*
# Числа Фибоначчи

Последовательность [чисел Фибоначчи](https://ru.wikipedia.org/wiki/Числа_Фибоначчи)
определяется формулой F(n) = F(n-1) + F(n-2).
То есть, следующее число получается как сумма двух предыдущих.

Первые два числа равны 1, затем 2(1+1), затем 3(1+2), 5(2+3)
и так далее: 1, 1, 2, 3, 5, 8, 13, 21....

Напишите функцию fib(n) которая возвращает n-е число Фибоначчи.

Пример работы:

fib(3); // 2
fib(7); // 13
fib(77); // 5527939700884757

P.S. Все запуски функций из примера выше должны работать быстро.
Вызов fib(77) должен занимать не более доли секунды.
*/
видел я в каком то докладе разбор такой ситуации, только не помню в каком
источник

Б

Богдан in JavaScript.Ninja
Den Pol
Если не завести переменную max - дина будет вычисляться на каждой итерации (+200 ms).
v8 давно умеет выносить за пределы цикла различные обращения а ручное вынесение длины массива в переменную может даже навредить (https://mrale.ph/blog/2014/12/24/array-length-caching.html)
источник

Б

Богдан in JavaScript.Ninja
Den Pol
Почему первый способ намного быстрее?

function fib(n) {
 // V1: LIGHT
 // const result = [];
 // eslint-disable-next-line no-plusplus
 // for (let i = 0; i < n; i++) {
 //   if (i === 0 || i === 1) {
 //     result.push(1);
 //   } else {
 //     result.push(result[i - 1] + result[i - 2]);
 //   }
 // }
 // return result[n - 1];

 // V2: HARD
 const arr = new Array(n);
 // eslint-disable-next-line no-plusplus
 for (let i = 0, max = arr.length; i < max; i++) {
   if (i === 0 || i === 1) {
     arr[i] = 1;
   } else {
     arr[i] = arr[i - 1] + arr[i - 2];
   }
 }

 return arr[n - 1];
}

console.time("fib(77)");
console.log(fib(77));
console.timeEnd("fib(77)");

// LIGHT:
// Output: "fib(77): 0.165ms"

// HARD:
// Output: "fib(77): 7.580ms"
то что HARD версия отработала дольше это некий артефакт первого запуска еще даже не разогретой функции, я вот сделал две функции fibLIGHT и fIbHARD и добавил код который будет вызывать их по таймеру
setInterval(() => {
 console.time("fibLIGHT(77)");
 console.log(fibLIGHT(77));
 console.timeEnd("fibLIGHT(77)");

 console.time("fibHARD(77)");
 console.log(fibHARD(77));
 console.timeEnd("fibHARD(77)");
}, 1000);

запустил на ноде и получил цифры что fibLIGHT занимает где-то 0.400-0.500мс а fibHARD занимает 0.200-0.300мс то есть получил противоположный результат - что fibHARD версия быстрее.
Ну а если взглянуть на ассемблер в который компилируются обе функции то можно увидеть что в fibLIGHT происходит вызов рантайм с++ функций GrowFastSmiOrObjectElements и GrowFastDoubleElements когда же в fibHARD версии таких вызовов нет. Оно и логично так как fibHARD аллоцирует массив только один раз а не занимается переаллокацией несколько раз (во время постоянного пуша в изначально пустой массив) как версия fibLIGHT
источник

IK

Illya Klymov in JavaScript.Ninja
Богдан
то что HARD версия отработала дольше это некий артефакт первого запуска еще даже не разогретой функции, я вот сделал две функции fibLIGHT и fIbHARD и добавил код который будет вызывать их по таймеру
setInterval(() => {
 console.time("fibLIGHT(77)");
 console.log(fibLIGHT(77));
 console.timeEnd("fibLIGHT(77)");

 console.time("fibHARD(77)");
 console.log(fibHARD(77));
 console.timeEnd("fibHARD(77)");
}, 1000);

запустил на ноде и получил цифры что fibLIGHT занимает где-то 0.400-0.500мс а fibHARD занимает 0.200-0.300мс то есть получил противоположный результат - что fibHARD версия быстрее.
Ну а если взглянуть на ассемблер в который компилируются обе функции то можно увидеть что в fibLIGHT происходит вызов рантайм с++ функций GrowFastSmiOrObjectElements и GrowFastDoubleElements когда же в fibHARD версии таких вызовов нет. Оно и логично так как fibHARD аллоцирует массив только один раз а не занимается переаллокацией несколько раз (во время постоянного пуша в изначально пустой массив) как версия fibLIGHT
Не все так просто
источник

IK

Illya Klymov in JavaScript.Ninja
Посмотрите что будет если там не 77 элементов будет а 2000 :)
источник