Авторы явно забыли добавить подобные вопросы к мидлу:
— Сколько извесных людей из мира JS знаете лично
и сеньору:
— Сколько извесных людей из мира JS занют вас лично
основною структурою буде завжди хеш таблиця (не має значення чи то об’єкт чи його похідна — массив)..
— ні. у випадку об’єкта — це буде хеш таблиця. у випадку Array — буде List. ryanpeden.com/...rays-work-under-the-hood.
Да верно, забыл об этом:
PACKED_SMI_ELEMENTS — a packed integer array
PACKED_DOUBLE_ELEMENTS — a packed double array
PACKED_ELEMENTS — a packed object array
HOLEY_SMI_ELEMENTS — a sparse integer array
HOLEY_DOUBLE_ELEMENTS — a sparse double array
HOLEY_ELEMENTS — a sparse object array
DICTIONARY_ELEMENTS — a very sparse array that is backed by a dictionary
И собственно еще одно правил:
4) По возможности, данные в JS массиве должы быть однородны
const start = new Date();
const obj = JSON.parse(jsonStr);
console.log(`${new Date().getTime() - start.getTime()}ms`, jsonStr.length);
Согласен, проверял на удаленной машине, получил завышенные результаты.
Поэтому мой акцент в том, что парсинг явдяется настолько критичен в корне не верен. Хотя это блокирующая операция и для определеных задач может быть проблеммой.
Відповідь приходить за 300 мілісекунд
Очень хорошо, но это по прежнему самая медленная часть, ускорение которой и должна привести к основному росту производительности.
Вы не внимательно прочитали мой ответ и повторяете мои слова как утверждение мне же:
файла приблизно 3.3мб у запакованому вигляді приблизно 200кб
Тоді додав CDN, він цей файлик зжимає через gzip і маємо 200кб.
Насчет моих расчетов:
(800 + 100 + 2) * 1000 / (1000 * 60) ≈ 15 хвилин.
Це все в разрахунку для синхронного коду.
Это предположение было заведомо упрощением, и я как раз про это и пишу. Т.к. исходные характеристики сервера который будет отдавать мне эти данные не известны, я могу лишь описать худший вариан.
З цифр випливае наступна оптимізація по порядку:
1) Тримати відкрите підключення, чи пул підключень до сервера
2) Змінити формат данних, щоб уникнути парсинга великого за об’ємом JSON (наприклад стрімити чанки JSON/CSV)
3) Оптимизувати алгоритм, якщо це стало bottleneck
4) Замінити Nodejs на більш «продуктивний» сервер чи змінити подхід до агрегації данних (наприклад використовувати спеціалізовані БД)
Цікавий висновок. Спочатку показати, що в нас 800 — це найбільший таймаут (сторонній API + мережа), а потім сказати, «4) Замінити Nodejs на більш „продуктивний“ сервер».
Я привел нумерованый список оптимизации в порядке убывание важности их решения. Когда дело дойдет до момента когда Nodejs не будет справляться с задачей, то да, лучше ее заменить.
Нода виконує операції Event Loop в одному потоці. Але це не означає, що I/O операції також повинні виконуватися в одному потоці. Нода використовує багатопоточність, але вона схована від розробника.
Все же мне кажется, что основное преимущество Nodejs — это асинхронность, а не многопоточнось.
Можете мне ответить на одни вопрос. Нужно ли столько «оптимизировать» если изначально оталкиваться в написании кода на Nodejs от неких парадигм, например:
1.
основною структурою буде завжди хеш таблиця (не має значення чи то об’єкт чи його похідна — массив).
2. Не блокируй EventLoop.
2.
Ипользовании сторонней библиотеки, где нативная конструкция занимает столько же места это антипатерн.
3. Избегать вложенных циклов, где это возможо (Плоское лучше, чем вложенное — The Zen of Python, by Tim Peters).
И да, я не говорю, что не нужно знать базовые алгоритмы и структуры данных.
Добре, припустимо, що задача побудувати сервис, який би отимував данні зі сторонього ресурсу для 1000 міст раз на годину та робив по ним агрегацію. Доречі, для работи з большою кількостью за об’ємом та трафиком данних, що требо бистро серелізувати/десерелізувати, Nodejs не дуже підійде, бо це CPU bound EventLoop блокуючий процесс.
Якщо грубо підрахувати:
Розмір файла приблизно 3.3мб у запакованому вигляді приблизно 200кб(цифри отримав з браузеру). Загрузка одного файлу з ресурсу якщо встановлювати з’єднання то > 800 мс у Firefox. Для простоти вважаемо що разпаковка файла 0 мс, далі йде парсинг JSON.parse > 100 мс (прогнав пару раз на локальной машині с данними) далі логіка
При прочих сталих в найгиршому випадку маємо: (800 + 100 + 176) * 1000 / (1000 * 60) ≈ 18 хвилин, а для найкращого: (800 + 100 + 2) * 1000 / (1000 * 60) ≈ 15 хвилин.
Це все в разрахунку для синхронного коду.
З цифр випливае наступна оптимізація по порядку:
1) Тримати відкрите підключення, чи пул підключень до сервера
2) Змінити формат данних, щоб уникнути парсинга великого за об’ємом JSON (наприклад стрімити чанки JSON/CSV)
3) Оптимизувати алгоритм, якщо це стало bottleneck
4) Замінити Nodejs на більш «продуктивний» сервер чи змінити подхід до агрегації данних (наприклад використовувати спеціалізовані БД)
Но зі статті випливає, що єдиною оптимізацією є алгорітм.
Вся «оптимізація» в таких випадках, це ефективно використання особливості JS, що основною структурою буде завжди хеш таблиця (не має значення чи то об’єкт чи його похідна — массив).
Спасибо за статью! Не планировали расширить тест фреймворки, скажем, Siege, Artillery,
Hey, Yandex Tank? Или может написать обзор по зоопарку инструментов тестирования и когда какой лучше применять?
Дуже суб’єктивні твердження. Дайте об’єктивні метрики, щоб можна було почати діалог.
Тобто ви вважаєте, що такий спосіб ітерації по масиву це нормально?
while (source.length > 0) { source.splice(0, 1); }
Ваша перша оптимізація заключалася в виклученні бібліотекі та заміну її на нативний код, чому вас дивує ствердження:
Ипользовании сторонней библиотеки, где нативная конструкция занимает столько же места это антипатерн.
Далі ви використовуєте lodash для простих операцій, котрі теж можно замінити на нативний код.
В последнем примере у вас лишняя операция (создание массива с ключами
Затегайте код, напишіть, як має виглядати за вашою версією, покажіть різницю продуктивності.
const dates = Object.keys(groupedByDate);
const meanTemperaturesByDate: { date: string, meanTemperature: number }[] =
dates.map(date => {
const temperaturesInOneDay = groupedByDate[date];
return {
date,
meanTemperature: _.meanBy(temperaturesInOneDay, item => item.temperature)
}
})
Можно замінити на:
const meanTemperaturesByDate = [];
for (const date in groupedByDate) {const meanTemperature = groupedByDate[date].reduce((a,b) => a + b) / groupedByDate[date].length
meanTemperaturesByDate.push({ date, meanTemperature })
}
Але все це не оптимізація, а написання логічного кода з використанням структур данних та інструментів які є в цій мові програмування.
Ви намалювали «сферичного коня в вакуумі» для сладной сістемі спростивши її у зручний вам спосіб, тому всі ці запитання й з’явилися. Чому ви вичитуєте у пам’ять вихідний JSON, хоча серелізація цього об’єкту є самою затратною операцією і JSON.parse блокує Event Loop? Чому на останьому етапі підіймаєте ще один сервіс, коли даже с першим варіантом кода та кешем можно було б збільшити показники відповіді в рази по відношенню з останнім кодом? Чому ви взяли js код як приклад оптимізації, коли вся оптимізація трапляеться в ньому under the hood і метрики продуктивності дуже залежать від системи та способа вимірювання?
А можно лінк де написано, що масив у JS це не об’єкт.
Радий тебе чути! Дякую за службу!