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

1
5898
Добавить в избранное

Рассмотрим 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 раз!

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

Перевод статьи Yotam Kadishay: 3 JavaScript Performance Mistakes You Should Stop Doing

Другие статьи по теме:

Хотите получать больше интересных материалов с доставкой?

Подпишитесь на нашу рассылку:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




1 комментарий

Оставьте комментарий