сократите время выполнения кода javascript

12 советов по улучшению производительности JavaScript-приложений

Производительность — это один из важнейших вопросов, встающих перед разработчиками веб-страниц или веб-приложений. Никто не будет рад «падающему» от чрезмерной нагрузки приложению, или странице, которая загружается целую вечность. Пользователи веб-сайтов не готовы слишком долго ждать их загрузки или приведения их страниц в рабочее состояние. Согласно данным Kissmetrics, 47% посетителей ожидают, что веб-сайт загрузится менее чем за 2 секунды. 40% посетителей покинут сайт в том случае, если его загрузка займёт более 3 секунд.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Автор материала, перевод которого мы сегодня публикуем, говорит, что, если учитывать вышеприведённые цифры, становится ясно, что производительность — это то, о чём всегда стоит помнить веб-разработчикам. Здесь будут приведены 12 рекомендаций по улучшению производительности JS-проектов.

1. Пользуйтесь кэширующими механизмами браузеров

Существует два основных способа кэширования данных средствами браузеров. Первый — использование JavaScript-API Cache, работа с которым осуществляется с помощью сервис-воркеров. Второй — это обычный HTTP-кэш.

Скрипты часто используются для организации доступа к определённым объектам. Если хранить ссылку на объект, к которому часто требуется доступ, в переменной, а также если использовать эту переменную в повторяющихся операциях, при выполнении которых требуется доступ к объекту, можно добиться улучшения производительности кода.

2. Оптимизируйте код в расчёте на те среды, в которых он будет выполняться

Для того чтобы адекватно оценивать улучшения, вносимые в программу, рекомендуется сформировать набор сред, в которых можно провести измерения.

На практике вам не удастся выполнять исследования производительности кода, например, во всех существующих версиях JS-движков, равно как и оптимизировать код в расчёте на все среды, в которых он может выполняться. Но надо отметить, что тестирование кода в какой-то одной среде — тоже не лучшая практика. Такой подход может дать искажённые результаты. Поэтому важно сформировать набор сред, в которых, вероятнее всего, будет выполняться код, и тестировать проекты в этих средах.

3. Избавляйтесь от неиспользуемого JS-кода

Благодаря удалению из проекта неиспользуемого кода улучшится не только время загрузки скриптов браузерами, но и время, необходимое браузерам на то, чтобы проанализировать и скомпилировать код. Для того чтобы избавиться от неиспользуемого кода стоит обратить внимание на особенности работы проекта. Так, если вы обнаружили некий функционал, с которым не работают пользователи — рассмотрите возможность убрать его из проекта, а заодно — и связанный с ним JS-код. В результате сайт будет загружаться быстрее, он будет быстрее подготавливаться к работе в браузере. Это благотворно скажется на тех впечатлениях, которые работа с сайтом вызовет у пользователей. Анализируя проект, учитывайте, что, например, некая библиотека, включённая в его состав, может быть включена в него по ошибке. Она вполне может реально в нём не использоваться. От неё стоит избавиться. То же самое касается использования неких зависимостей, которые реализуют то, что уже реализовано в современных браузерах. Как результат, переход на стандартные возможности браузеров, дублируемые этой зависимостью, поможет избавиться от ненужного кода.

4. Экономно расходуйте память

Стоит стремиться к тому, чтобы веб-проекты использовали бы лишь ту память, без которой они абсолютно не в состоянии обойтись. Дело в том, что разработчику нельзя заранее узнать о том, сколько памяти может быть доступно его приложению на некоем устройстве. Если приложение неоправданно использует большие объёмы памяти — это создаёт повышенную нагрузку на механизмы управления памятью браузерного JS-движка. В частности, это касается сборщика мусора. Частые вызовы сборщика мусора приводят к замедлению работы программ. Это негативно влияет на удобство работы с проектом.

5. Используйте механизмы отложенной загрузки для второстепенных скриптов

Пользователи хотят, чтобы веб-страницы загружались бы как можно быстрее. Но вряд ли для начального отображения страницы нужен абсолютно весь JS-код проекта. Если пользователю, чтобы задействовать некий код, нужно выполнить какое-то действие (например, щёлкнуть по некоему элементу или перейти на какую-нибудь вкладку в приложении), то загрузку этого кода можно отложить, выполнив её после первоначальной загрузки страницы и самых важных ресурсов.

При таком подходе можно избежать загрузки и компилирования браузером большого объёма JS-кода в самом начале работы, то есть — избежать замедления вывода страницы, вызванного необходимостью выполнения этих операций. После того, как завершится загрузка всего самого важного, можно начать загружать дополнительный код. В результате, когда этот код понадобится пользователю, он уже будет ему доступен. В соответствии с моделью RAIL Google рекомендует выполнять сеансы отложенной загрузки скриптов длительностью порядка 50 мс. При таком подходе операции по загрузке кода не повлияют на взаимодействие пользователя со страницей.

6. Избегайте утечек памяти

Если в вашем приложении случилась утечка памяти, то это выразится в том, что загруженная страница будет запрашивать у браузера всё больше и больше памяти. В результате потребление памяти этой страницей может достичь такого уровня, что это плохо повлияет на производительность всей системы. Вероятно, вы и сами сталкивались с подобной проблемой (и вам это, наверняка, не понравилось). Вполне возможно, что страница, на которой имелась утечка памяти, содержала некое средство просмотра изображений — вроде слайдера или «карусели».

В инструментах разработчика Chrome можно проанализировать сайт на предмет утечек памяти. Делается это путём исследования показателей средствами вкладки Performance. Обычно утечки памяти исходят из-за фрагментов DOM, удалённых со страницы, но привязанным к каким-то переменным. Это не позволяет сборщику мусора очистить память, занимаемую данными ненужными фрагментами DOM.

7. Если вам нужно выполнить некие тяжёлые вычисления — используйте веб-воркеры

Из материалов ресурса MDN можно узнать о том, что веб-воркеры позволяют запускать код в фоновом потоке, отделённом от главного потока веб-приложения. Преимущество такого подхода заключается в том, что тяжёлые вычисления могут быть выполнены в отдельном потоке. Это позволяет главному потоку (обычно ответственному за обеспечение работы пользовательского интерфейса) выполняться без блокировок и замедлений.

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

8. Если вы обращаетесь к элементу DOM несколько раз — сохраните ссылку на него в переменной

9. Стремитесь объявлять переменные в той же области видимости, в которой они будут использоваться

JavaScript, при попытке доступа к переменной, сначала ищет её в локальной области видимости. Если её там не оказывается — поиск продолжается в областях видимости, в которую вложена локальная область видимости. Так происходит до тех пор, пока проверке не подвергнутся глобальные переменные. Сохранение переменных в локальных областях видимости ускоряет доступ к ним.

10. Старайтесь не использовать глобальные переменные

Глобальные переменные существуют в течение всего времени работы скрипта. Локальные же переменные уничтожаются при уничтожении локальной области видимости. Поэтому глобальными переменными стоит пользоваться лишь тогда, когда это действительно необходимо.

11. Применяйте в JavaScript оптимизации кода, которые вы применяли бы и к программам, написанным на других языках

12. Используйте инструменты для исследования производительности приложений

Для исследования различных аспектов веб-проектов можно порекомендовать инструмент Lighthouse. Он выставляет приложению оценки по следующим показателям: Performance, Progressive Web App, Accessibility, Best Practices, SEO. Lighthouse не только выставляет оценки, но и даёт рекомендации по улучшению проекта. Ещё одно средство для анализа производительности, Google PageSpeed, создано для того, чтобы помочь разработчикам исследовать свои сайты и увидеть направления их возможного улучшения.

И Lighthouse, и PageSpeed — инструменты не идеальные, но их использование помогает увидеть проблемы, которые, на первый взгляд, могут оказаться незаметными.

В меню Chrome можно найти команду, открывающую диспетчер задач. Там выводятся сведения о системных ресурсах, используемых открытыми вкладками браузера. Более подробные сведения о том, что происходит на странице, можно получить, открыв вкладку Performance инструментов разработчика Chrome (подобные инструменты есть и в других браузерах). Эта вкладка позволяет анализировать множество показателей, касающихся производительности сайта.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Вкладка Performance в инструментах разработчика Chrome

В ходе сбора сведений о производительности страниц средствами Chrome можно настраивать доступные страницам процессорные и сетевые ресурсы, что позволяет выявлять и исправлять проблемы.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Анализ производительности страницы в Chrome

Для того чтобы глубже проанализировать веб-сайт — можно воспользоваться API Navigation Timing. Оно позволяет выполнять измерения различных показателей прямо в коде приложения.

Если вы разрабатываете на JavaScript серверные проекты с использованием Node.js, то вам, для глубокого анализа своих приложений, можно воспользоваться платформой NodeSource. Измерения, проводимые средствами этой платформы, оказывают незначительное воздействие на проект. В среде Node.js, как и в браузере, может возникать множество проблем — вроде тех же утечек памяти. Анализ проектов, основанных на Node.js, помогает выявлять и устранять проблемы с их производительностью.

Итоги

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

Кроме того, полезно помнить о том, что производительность стоит принимать в расчёт всегда, но она не должна быть важнее обеспечения безошибочной работы кода и реализации нужных пользователям возможностей приложений.

Уважаемые читатели! Как вы оптимизируете свои JS-проекты?

Источник

Оптимизация первой задержки ввода

Как быстрее реагировать на взаимодействие с пользователем.

«Я нажал, но ничего не произошло! Почему я не могу взаимодействовать с этой страницей?» 😢

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Чтобы помочь предсказать FID в lab, рекомендуется общее время блокировки (TBT). Они измеряют разные вещи, но улучшения в TBT обычно соответствуют улучшениям в FID.

Основной причиной плохого FID является тяжелое выполнение JavaScript. Оптимизация анализа, компиляции и выполнения JavaScript на вашей веб-странице напрямую сократит FID.

Тяжелое выполнение JavaScript

Браузер не может отвечать на большинство пользовательских вводимых данных, пока он выполняет JavaScript в основном потоке. Другими словами, браузер не может реагировать на взаимодействие с пользователем, пока основной поток занят. Чтобы улучшить это нужно:

Сократить время выполнения JavaScript

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

Чтобы уменьшить количество JavaScript, выполняемого на вашей странице нужно:

Помимо минимизации JavaScript, разбитие долго выполняющегося кода на более мелкие задачи, может позволить браузеру быстрее запускать обработчики ввода, что может улучшить FID.

Сократить и сжать файлы JavaScript

JavaScript может содержать символы, которые не нужны для браузеров, но облегчают чтение во время разработки. Это включает в себя интервалы, отступы, комментарии и длинные имена переменных.

Terser поддерживает синтаксис ES6+ и может использоваться для минимизации современных файлов JavaScript без необходимости их транспилирования. Если вы используете связку модулей и хотите включить Terser в свою цепочку инструментов:

В дополнение к минимизации, сжимайте ваши ресурсы JavaScript, чтобы минимизировать размер их доставки. Если возможно, используйте Brotli, который обеспечивает лучшие результаты сжатия, чем Gzip, и может использоваться практически во всех новых браузерах.

Отложить неиспользованный JavaScript

По умолчанию весь JavaScript блокирует рендеринг. Когда браузер обнаруживает тег сценария, который ссылается на внешний файл JavaScript, он должен приостановить выполнение своих действий и загрузить, проанализировать, скомпилировать и выполнить этот JavaScript. Поэтому вам следует загружать только тот код, который необходим для страницы или отвечает на ввод пользователя.

На вкладке Coverage в Chrome DevTools можно указать, сколько JavaScript не используется на вашей веб-странице.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Чтобы сократить неиспользуемый JavaScript необходимо:

Динамический импорт JavaScript для определенных взаимодействий пользователя (таких как изменение маршрута или отображение модального режима) обеспечит выбор кода, не используемого для начальной загрузки страницы, только при необходимости.

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

Помимо разделения кода, всегда используйте async или defer для сценариев, которые не нужны для критического пути или содержимого, превышающего сложность.

Минимизируйте неиспользуемые полифилы

Если вы создаете свой код с использованием современного синтаксиса JavaScript и ссылаетесь на API-интерфейсы современных браузеров, вам потребуется перенести его и включить полифиллы, чтобы он работал в старых браузерах.

Одной из основных проблем производительности, связанной с включением на ваш сайт полифилов и переносимого кода, является то, что более новым браузерам не нужно загружать их, если они им не нужны. Чтобы сократить размер JavaScript вашего приложения, максимально сведите к минимуму неиспользуемые полифилы и ограничьте их использование средами, где они необходимы.

Для оптимизации использования полифилла на вашем сайте:

Многие новые функции ECMAScript, скомпилированные с помощью Babel, уже поддерживаются в средах, поддерживающих модули JavaScript. Таким образом, делая это, вы упрощаете процесс проверки того, что только транспилированный код используется для браузеров, которые действительно нуждаются в нем.

Разбейте длинные задачи

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

Разделение длинных задач может уменьшить задержку ввода на вашем сайте.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

FID должен заметно улучшиться, поскольку вы принимаете лучшие практики, такие как разделение кода и разбитие ваших длинных задач. Хотя TBT не является полевой метрикой, он полезен для проверки прогресса и в конечном счете улучшения как времени до интерактивного (TTI), так и FID.

Оптимизация страницы для взаимодействия готовности

Существует ряд распространенных причин плохой оценки FID и TBT в веб-приложениях, которые сильно зависят от JavaScript:

Выполнение сценария первого лица может задержать готовность к взаимодействию #

Ниже приведены оценки TBT до и после оптимизации загрузки сценариев первой стороной для приложения. Перемещая дорогостоящую загрузку скрипта (и выполнение) для несущественного компонента критического пути, пользователи могли взаимодействовать со страницей гораздо раньше.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Выборка данных может влиять на многие аспекты готовности взаимодействия

Выборка данных может влиять на многие аспекты готовности взаимодействия

Использование веб-работника

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

Рассмотрите возможность использования следующих библиотек, чтобы упростить использование веб-работников на вашем сайте:

Инструменты разработчика

Доступен ряд инструментов для измерения и отладки FID:

Lighthouse 6.0 не включает поддержку FID, так как это метрика поля. Тем не менее, общее время блокировки (TBT) может использоваться в качестве прокси. Оптимизации, которые улучшают TBT, также должны улучшить FID на местах.

сократите время выполнения кода javascript. Смотреть фото сократите время выполнения кода javascript. Смотреть картинку сократите время выполнения кода javascript. Картинка про сократите время выполнения кода javascript. Фото сократите время выполнения кода javascript

Chrome User Experience Report предоставляет реальные значения LCP, агрегированные на уровне источника.

Источник

13 советов, как сделать код на JavaScript качественнее и быстрее

Способы оптимизации кода: от простых до роскошных

10 лет назад компания Amazon подсчитала, что 100 миллисекунд задержки стоили ей 1% выручки с продаж. Аналогичным образом в Google обнаружили, что дополнительные 500 миллисекунд на генерацию поисковых страниц сократили их трафик на 20%, на столько же урезав потенциальный доход от рекламы. Оказывается, скорость действительно решает всё. Мы публикуем перевод статьи британского разработчика Брета Кэмерона, в которой он дает 13 практических советов для увеличения скорости работы JavaScript-кода.

Меньше — лучше

Самый быстрый код — это код, который никогда не будет запущен

1. Удалите ненужные функции

Можно сразу приступить к оптимизации написанного кода, но часто наибольший прирост производительности достигается, если сделать шаг назад и спросить себя: нужен ли тот или иной сегмент на самом деле? Прежде чем перейти к оптимизации, спросите себя: должна ли ваша программа делать всё, что она делает? Необходимы ли все эти возможности, компоненты и функции? Если нет, удалите ненужное. Этот шаг невероятно важен для повышения скорости работы вашего кода, но про него легко забыть.

2. Избегайте ненужных шагов

Начав детально пересматривать код, спросите себя: каждый ли сделанный шаг необходим для успешного выполнения функции и достижения нужного результата? Например, не проходят ли данные через ненужные циклы? Следующий пример намеренно упрощен, но такое сложнее обнаружить в большой кодовой базе:

Даже в этом простом примере разница в производительности огромна: маленький работающий код быстрее большого неработающего. Хотя вышеописанную ошибку допускают немногие, в большом коде легко проглядеть лишние шаги, если нужный результат достигается. Избегайте их.

Реже — лучше

Если вы не можете удалить фрагмент кода, постарайтесь выполнять его реже

Ваш код работает в том числе за счет простого повторения операций, но тут легко переборщить и начать выполнять их чаще необходимого. Вот несколько конкретных примеров, на которые стоит обратить внимание.

3. Циклы должны завершаться как можно раньше

Обращайте внимание, есть ли необходимость выполнять каждую итерацию цикла. Например, если вы ищете конкретное значение и находите его, нет смысла в дальнейших итерациях, лучше прервать выполнение цикла оператором break:

Или, если нужно произвести операции с определенными элементами цикла, вы можете пропустить другие операции с помощью оператора continue, который останавливает выполнение операторов в текущей итерации и немедленно переходит к следующей:

Стоит также помнить, что вложенные циклы можно разрывать с помощью меток. Это позволяет привязать оператор break или continue к определенному циклу:

4. Предвычисляйте, если возможно

Возьмем следующую функцию, в нашей программе мы хотим её вызвать несколько раз:

Проблема этого кода в том, что каждый раз, когда мы вызываем функцию whichSideOfTheForce, мы создаем новый объект. При каждом вызове функции под наши массивы без необходимости выделяется память. Учитывая, что «светлые» и «темные» значения статичны, лучшим решением было бы объявить эти переменные один раз, а затем ссылаться на них при вызове whichSideOfTheForce. Мы могли бы определить наши переменные в глобальной области видимости, но тогда они могли бы изменяться за пределами нашей функции. Лучшее решение — задействовать замыкание, чтобы функция вернула своё значение:

Теперь массивы «света» и «тьмы» будут создаваться всего один раз. То же самое относится к вложенным функциям. Например:

Каждый раз, когда мы запускаем doSomething, вложенная функция создается с нуля. Замыкание поможет и здесь. Если мы возвращаем функцию, doSomethingElse остается закрытой, но создается всего один раз:

5. Минимизируйте количество операций в коде

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

Функция должна делать две вещи: конвертировать центы в доллары и суммировать элементы, но важно соблюсти порядок операций. Для конвертации в доллары мы могли бы использовать следующую функцию:

Но в этом случае мы выполняем операцию деления в каждом элементе массива. Поставив операции в обратном порядке, мы должны будем выполнить деление только один раз:

Ключевой момент — обеспечить выполнение операций в наилучшем порядке.

6. Изучите О-нотацию

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

По сути, О-нотация помогает применять и понимать описанные в этой статье способы оптимизации. Это глубокая тема, поэтому, если вам интересно узнать больше, я рекомендую прочитать мою статью об О-нотации или статью, где я разбираю четыре варианта решения задач на собеседовании в Google в контексте затраченного времени и пространственной сложности алгоритма.

Ускоряйте исполнение

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

7. Используйте встроенные инструменты

Для тех, кто имеет опыт работы с компиляторами и низкоуровневыми языками, этот момент может показаться очевидным. Если нужные вам инструменты уже содержатся в самом JavaScript «из коробки», используйте именно их.

Код компилятора оптимизирован с точки зрения производительности конкретных методов и типов объектов. Кроме того, базовым языком для JavaScript служит C++. Если у вас не очень специфичный случай, вероятность того, что ваша собственная реализация JavaScript превзойдет существующие методы, крайне мала.

Чтобы проверить, создадим собственную JavaScript-реализацию Array.prototype.map:

Теперь давайте создадим массив из 100 случайных чисел от 1 до 100:

Даже если мы хотим выполнить простую операцию, например, умножить каждое целое число в массиве на два, мы всё равно увидим разницу в производительности:

В моих тестах новая функция map JavaScript оказалась примерно на 65% медленнее, чем Array.prototype.map. Чтобы посмотреть исходный код реализации Array.prototype.map движка V8, кликните сюда. А чтобы провести тесты самому, кликните по ссылке на оценочный тест.

8. Используйте объекты, наиболее подходящие для конкретной задачи

Как и в предыдущих пунктах, наилучшая производительность достигается за счет выбора соответствующего объекта для решения текущей задачи. Встроенные в JavaScript объекты хорошо дополняют примитивные типы данных: числа, строки, функции, объекты и так далее. При использовании в верном контексте многие из этих менее распространенных объектов могут дать значительные преимущества в производительности.

В других статьях я писал о том, что использовать Set может быть быстрее, чем Array, а Map — чем регулярные объекты. Set и Map — это коллекции, которые используют ключи, они могу пригодиться, если вы регулярно добавляете или удаляете значения. Познакомьтесь со встроенными типами объектов и всегда используйте лучший инструмент из доступных, так вы сможете сделать код быстрее.

9. Не забудьте про память

Будучи высокоуровневым языком, JavaScript учитывает нюансы более низких уровней. Один из таких нюансов — управление памятью. JavaScript использует систему сбора «мусора» для высвобождения данных из памяти (если только явно не прописать в коде, что эти данные всё ещё нужны).

Хотя управление памятью в JavaScript выполняется автоматически, это не означает, что оно безупречно. Есть дополнительные шаги, которые можно предпринять для управления памятью и снижения вероятности утечек памяти.

Например, у функций Set и Map есть так называемые слабые вариации (WeakSet и WeakMap). Они содержат «слабые» ссылки на объекты. Они не используют тип enumerable, но они предотвращают утечку памяти, так как позволяют отправлять в «мусор» не упомянутые в коде значения.

Вы также можете лучше контролировать распределение памяти, используя объекты TypedArray, представленные в обновлении JavaScript ES2017. Например, Int8Array может принимать значения от –128 до 127 и имеет размер всего в один байт. Стоит отметить, однако, что прирост производительности при использовании объектов TypedArray может быть очень мал: сравнение обычного массива и Uint32Array показывает небольшое улучшение производительности записи, но незначительное или нулевое улучшение производительности чтения (спасибо Крису Ху за оба теста).

Поняв низкоуровневый язык программирования, вы сможете быстрее и лучше писать код на JavaScript. Об этом я пишу подробнее в своей статье «Как C++ может помочь JavaScript-разработчикам».

10. Используйте мономорфные операции, если возможно

Если присвоить переменной a значение 2 с помощью const, то её можно считать полиморфной (ее можно изменить). Напротив, если мы будем непосредственно использовать числовое значение 2, то его можно считать мономорфным (его значение фиксировано).

Конечно, полезно присваивать переменным значения, если нам нужно использовать их несколько раз. Если вы используете переменную только один раз, немного быстрее будет, если не устанавливать переменную вовсе. Возьмем простую функцию умножения:

Если запустить функцию multiply(2, 3), она завершится примерно на 1% быстрее, чем если запустить такой код:

Это довольно мало. Но в большой кодовой базе подобные маленькие победы складываются в большую. Таким же образом использование аргументов в функциях дает гибкость в ущерб производительности. Опять же, аргументы — это неотъемлемая часть программирования. Но если они вам не нужны, вы получите преимущество в производительности, если не будете их использовать. Еще более быстрая версия нашей функции умножения может выглядеть так:

Как я отметил ранее, улучшение производительности невелико (в моих тестах около 2%). Но если такое улучшение может быть использовано многократно в большой кодовой базе, то стоит подумать об этом. Как правило, вводить аргументы стоит тогда, когда значение динамическоe, а переменные вводятся только тогда, когда будут использоваться несколько раз.

11. Избегайте оператора delete

Оператор delete используется для удаления содержания из объекта. Может показаться, что он вам необходим, но если вы можете обойтись без него, то сделайте это. В движке V8 есть паттерн скрытых классов, и delete лишает вас преимуществ этого паттерна, делая объект обычным и медленным. А операции с медленными объектами — всё верно — выполняются медленнее.

В зависимости от ваших потребностей можно определить нежелательное свойство как неопределенное и, возможно, этого будет достаточно:

Я видел в интернете предположения, что было бы быстрее создать копию первоначального объекта без определенных свойств, используя следующие функции:

Однако в моих тестах функция, описанная выше, и некоторые другие работали даже медленнее, чем оператор delete. Кроме того, такие функции менее удобочитаемые, чем delete obj.a или obj.a = undefined.

В поисках альтернативы подумайте, можно ли использовать Map вместо объекта, так как Map.prototype.delete работает быстрее, чем оператор delete.

Откладывайте исполнение

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

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

12. Используйте асинхронный код для предотвращения блокировки потока

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

Решение можно найти через асинхронный код. Некоторые встроенные инструменты работают так по умолчанию (вроде fetch() или XMLHttpRequest()), но стоит также отметить, что любую синхронную функцию можно сделать асинхронной. Если у вас длительная (синхронная) операция, например, операция над каждым из элементов в большом массиве, то такой код можно сделать асинхронным, чтобы он не блокировал выполнение другого кода. Если вы новичок в асинхронном коде JavaScript, ознакомьтесь с моей статьей «Что обещает JavaScript».

Кроме того, многие модули (например, файловая система Node.js) имеют асинхронные и синхронные варианты некоторых функций (например, fs.writeFile() и fs.writeFileSync()). В обычных условиях придерживайтесь стандартного асинхронного подхода.

13. Используйте разделение кода

Если вы используете JavaScript на стороне клиента, ваши приоритеты должны быть сосредоточены в визуальном быстродействии. Главный оценочный критерий — это First Contentful Paint (FCP), время, за которое появляется первый полезный для пользователя контент в DOM-элементах.

Разделение кода — один из лучших способов улучшить ситуацию. Вместо того, чтобы подавать ваш JavaScript-код одним большим файлом, подумайте о том, чтобы разделить его на более мелкие фрагменты. Как вы будете разбивать код, зависит от того, используете ли вы один из фреймворков (React, Angular, Vue) или обходитесь стандартными средствами самого JavaScript.

Tree shaking — связанная с описанным кодом тактика статического анализа всего кода и исключения того, что на самом деле не используется. Чтобы узнать больше, я рекомендую эту статью от Google. Не забывайте оптимизировать свой код!

Заключение

Тестирование — лучший способ проверить, удалось ли вам оптимизировать код. В этой статье я привожу примеры кода, используя http://jsperf.com, но можно проверять и меньшие сегменты коды здесь:

Что касается проверки производительности веб-приложений, отличной отправной точкой являются разделы Chrome Dev Tools про сети и производительность. Также рекомендую расширение Lighthouse от Google.

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

Если вы новичок, надеюсь, этот материал открыл вам глаза на некоторые способы повышения производительности кода. А если вы опытный разработчик, надеюсь, что эта статья послужила полезным дополнением к вашим знаниям.

Источник

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

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