Нажмите "Enter" для перехода к содержанию

3 главные ошибки, которые вредят производительности JavaScript

0

Рассмотрим 3 главные ошибки, вызывающие спад производительности JavaScript кода, тестируем и избавляемся от «вредных привычек».

Что если ключевые функции ECMAScript, которые вы так кропотливо изучали, – не что иное, как опасная ловушка для снижения производительности JavaScript, красиво упакованная в однострочный функциональный код обратных вызовов?

Эта история началась с выходом ES5 и новых функций массивов ( forEach , reduce , map , filter и т. д.). С этими функциями возрастала функциональность языка. А написание кода становилось более слаженным и интересным. Да и результат работы выглядел проще и понятнее.

Тогда же активно развивалась и другая среда – Node.js. Она в корне пересматривала всю концепцию full-stack разработки и предлагала более плавный переход от front-end к back-end.

Поэтому Node.js с последним ECMAScript в V8 пытается выбиться в лидеры главных серверных языков программирования. А для этого он должен обладать высокой производительностью. Конечно же, нужно учитывать и множество других параметров. И да, универсального языка еще не придумали.

Так все же, JavaScript с его готовыми решениями – это польза или вред для производительности приложений?

С ростом мощности компьютеров и ускорением сети клиентская часть JavaScript становится отличным решением не только для представления/просмотра. Но можно ли положиться на JavaScript при написании высокопроизводительных приложений со сложной архитектурой?

Чтобы ответить на этот вопрос, проанализируем результаты тестирования нескольких операций (зацикливание, дублирование массива и перебор объектов). Все тесты проводились на macOS в Node.js v10.11.0 и браузере Chrome.

1. Зацикливание массива

Первое, что приходит на ум, – это найти сумму массива с 10 тыс. элементами. Пример взят из реальной практики, когда нужно извлечь огромную таблицу из базы данных и просуммировать ее значения, не создавая лишнего запроса к базе данных.
При суммировании случайных 10 тыс. элементов через операторы for , for-of , while , forEach и reduce 10 тыс. раз. получились значения ниже:

Если погуглить, как правильно суммировать массивы, то самым популярным советом будет использование оператора reduce . Однако данное решение является крайне медленными. Попытки реализовать задачу через forEach также не увенчались успехом. Даже в новейшем for-of (ES6) хромает производительность.

Оказалось, что лидерами по части производительности (в 10 раз быстрее остальных!) стали проверенные временем while и for .

Как же получилось, что новейшее и разрекламированное решение настолько сильно тормозит JavaScript? Дело тут в следующем: reduce и forEach требуют выполнения функции обратного вызова. Данная функция вызывается рекурсивно и заполняет стэк. Кроме того, торможение обусловлено и дополнительной операцией, а также проверкой исполняемого кода (см. тут).

2. Дублирование массива

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

При тестировании производительности получается интересный результат: дублирование 10 тыс. массивов из 10 тыс. случайных элементов лучше проводить классическими способами. Новомодная операция spread из […arr] , Array из Array.from(arr) в ES6 и map arr.map(x=> x) из ES5 позорно проигрывали «старичкам» slice arr.slice() и concatenate [].concat(arr) .

3. Перебор объектов

Еще одна популярная тема – перебор (итерация) объектов. Он нужен при переборе элементов JSON без поиска какого-либо конкретного значения ключа. Здесь тоже есть свои почетные ветераны – for-in for(let key in obj) или Object.keys(obj) (в ES6). Стоит вспомнить и Object.entries(obj) (в ES8), возвращающий ключи и значения.

Результаты тестирования 10 тыс. итераций объектов из 1 тыс. случайных ключей и значений в каждом:

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

Заключение

Если для приложения важна высокая производительность, или серверы сталкиваются с существенной нагрузкой, то забудьте про все популярные/легко читаемые/чистые решения. Они приводят к спаду производительности JavaScript кода в 10 раз!

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *