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

Измерение производительности JavaScript-функций

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

Если веб-проект обладает высокой производительностью — это вносит вклад в его позитивное восприятие пользователями. А если пользователям понравилось работать с ресурсом — они имеют свойство возвращаться. Например, в этом исследовании показано, что 88% онлайн-клиентов менее склонны возвращаться на ресурсы, при работе с которыми они столкнулись с какими-то неудобствами. Эти неудобства вполне могут быть вызваны проблемами с производительностью.

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

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

В этом материале я расскажу о том, как измерять производительность функций, и о том, что делать с результатами измерений.

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

Метод performance.now()

В Chrome после выполнения этого кода можно получить примерно такой результат:

Как видно, результаты измерений, полученные в разных браузерах, серьёзно различаются. Дело в том, что в Firefox 60 точность результатов, возвращаемых API Performance, снижена. Мы ещё поговорим об этом.

Интерфейс Performance обладает гораздо большими возможностями, чем только возврат некоей временной метки. К ним относятся измерение различных аспектов производительности, представленные такими расширениями этого интерфейса, как API Performance Timeline, Navigation Timing, User Timing, Resource Timing. Вот материал, в котором можно найти подробности об этих API.

Date.now() и performance.now()

Метод console.time()

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

После выполнения подобного кода система автоматически выведет в консоль сведения о прошедшем времени.

В Chrome это будет выглядеть примерно так:

Сильная сторона метода console.time() заключается в простоте его использования. А именно, речь идёт о том, что его применение не требует объявления вспомогательных переменных и нахождения разницы между записанными в них показателями.

Сниженная точность временных показателей

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

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

В Firefox 60, как уже было сказано, точность результатов измерения времени снижена. Это сделано с помощью установки значения свойства privacy.reduceTimerPrecision в значение 2 мс.

Кое-что, о чём стоит помнить, тестируя производительность

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

▍Разделяй и властвуй

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

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

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

▍Учитывайте особенности поведения функций при разных входных значениях

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

Функции при исследовании производительности нужно вызывать с входными данными, максимально напоминающими реальные.

▍Запускайте функции по много раз

Вот два варианта подобной функции:

После запуска кода мы получаем следующие результаты:

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

▍Тестируйте производительность в разных браузерах

Вышеприведённые тесты выполнялись в Firefox. А что если выполнить их в Chrome? Результаты будут совсем другими:

Дело в том, что браузеры Chrome и Firefox основаны на разных JavaScript-движках, в которых реализованы разные оптимизации производительности. Об этих различиях весьма полезно знать.

▍Применяйте искусственные ограничения системных ресурсов

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

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

При таком подходе 10 или 50 миллисекунд легко могут превратиться в 500.

▍Измеряйте относительную производительность

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

Итоги

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

Уважаемые читатели! Если вы постоянно контролируете производительность своих проектов, просим рассказать о том, как вы это делаете.

Источник

Как измерить время выполнения скрипта

Сегодня мы рассмотрим, сколько именно времени уходит у блока кода, чтоб выполнить свою работу?

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

Итак, первый способ, это использование специального метода в объекте console. Все знакомы с методом console.log(), с помощью которого можно выводить сообщения и смотреть отладочную информацию и ошибки. Кроме console.log() у объекта console существует метод time со специальным синтаксисом, который позволяет буквально в две строки замерять время выполнения блока вашего кода.

Для того, чтоб этот метод заработал, требуется в начале блока, который вы хотите непосредственно замерять, указать console.time() с ключом, как уникальным идентификатором, в нашем случае это будет FirstWay.

Далее идёт ваш блок кода, в нашем случае, это небольшая функция someFunction(). Когда ваш код уже выполнен и необходимо посмотреть на результат, сколько времени заняло его выполнение, вызывается специальный метод console.timeEnd() с тем же самым ключом, который вы задавали ранее.

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

Второй вариант считается более классическим подходом. В этом варианте больше строчек кода, но потребность в консоли отпадает. В этом методе требуется создать константу start. В ней мы объявляем объект new Date() с методом getTime() для установления начала отсчёта замера.

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

Когда скрипт выполнился, нужно создать новую константу end с объектом new Date() и методом getTime(), чтоб установить конец замера времени работы кода.

Далее, простым отниманием end — start мы и получим нужную разницу в миллисекундах и теперь нам известно, сколько времени ушло на выполнение кода.

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

Источник

Измерение производительности функций в JavaScript

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

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

Вероятно, у вас есть определённые подозрения относительно производительности часто используемых вами функций. Возможно, вы даже прикинули, как можно улучшить ситуацию. Но как вы измерите прирост производительности? Как можно точно и быстро протестировать производительность функций в JavaScript? Идеальный вариант — использовать встроенную функцию performance.now() и измерять время до и после выполнения ваших функций. Здесь мы рассмотрим, как это делается, а также разберём ряд подводных камней.

Performance.now()

С точки зрения математики монотонная функция либо только возрастает, либо только убывает. Другой пример, для лучшего понимания: переход на летнее или зимнее время, когда все часы в стране переводятся на час назад или час вперёд. Если мы сравним значения двух копий Date — до и после перевода часов, то получим, например, разницу «1 час 3 секунды и 123 миллисекунды». А при использовании двух копий performance.now() — «3 секунды 123 миллисекунды 456 789 тысячных миллисекунды». Не будем здесь подробно разбирать этот API, желающие могут обратиться к статье Discovering the High Resolution Time API.

Выполнение подобных функций можно измерить следующим способом:

Если выполнить данный код в браузере, то результат будет выглядеть так:

Ошибка № 1: случайное измерение ненужных вещей

Ошибка № 2: однократное измерение

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

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

Ошибка № 3: излишнее доверие к средним значениям

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

Обратите внимание, насколько самое первое значение отличается от остальных. Скорее всего, причина как раз в проведении субоптимизации и в необходимости «прогрева» компилятора. Мало что можно сделать, чтобы этого избежать, но зато можно обезопасить себе от неверных заключений.

Например, можно исключить первое значение и вычислить среднеарифметическое из остальных девяти. Но лучше взять все результаты и вычислить медиану. Результаты сортируются по порядку, и выбирается средний. Вот где performance.now() очень полезен, потому что вы получаете значение, с которым можно делать что угодно.

Итак, давайте измерим снова, но в этот раз используем срединное значение выборки:

Ошибка № 4: сравнение функций в предсказуемом порядке

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

Этот код можно улучшить, поскольку цикл haystack.forEach будет перебирать все элементы, даже если мы быстро нашли совпадение. Воспользуемся старым добрым for:

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

Получим такой результат:

Выводы

Ещё одна причина, почему мы не можем знать заранее, какой вариант будет быстрее, заключается в том, что всё зависит от ситуации. В последнем примере мы искали совпадение среди 26 значений вне зависимости от регистра. Но если мы будем искать среди 100 000 значений, то выбор функции может оказаться иным.

Источник

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

Javascript console.time

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

В javascript есть готовые конструкции кода для определения скорости выполнения скрипта.

Допустим мы хотим определить время вывода в консоль браузера сообщения тест:

В результате мы увидим в консоли:

Время выполнения скрипта: 2.19482421875ms

Время выполнения скрипта указывается в милисекундах. То есть вывод в консоль браузера текста у нас произошел за 2 милисекунды. Кто не знает 1 милисекунда это одна тысячная 1 секунды.

Для замера времени выполнения скрипта нужно его поместить между console.time() и console.timeEnd()

Как вы понимаете методы console.time() и console.timeEnd()являются отладочными и выводят результат в консоль браузера.

В качестве аргумента данные методы могут принимать строку которая также выводится в консоль. Отмечу аргументы методов console.time() и console.timeEnd() должны совпадать между собой, если мы попробуем вывести так:

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

Однако мы пользуясь данной особенностью можем делать интересные вещи:

Здесь нам в консоль выведется время выполнения каждой итерации цикла и в конце общее время выполнения цикла.

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

В общем пользуйтесь с умом. На этом данная статья подошла к концу.

Желаю вам удачи и успехов в программировании! Пока!

Оцените статью:

Статьи

Комментарии

Внимание. Комментарий теперь перед публикацией проходит модерацию

Все комментарии отправлены на модерацию

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

Запись экрана

Данное расширение позволяет записывать экран и выводит видео в формате webm

Источник

Как работает JS: обзор движка, механизмов времени выполнения, стека вызовов

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

Анализ статистики GitHub показывает, что по показателям активных репозиториев и push-запросов, JavaScript находится на первом месте, да и в других категориях он показывает довольно высокие позиции.

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

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

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

Как ни странно, существует множество разработчиков, которые регулярно пишут на JavaScript, но не знают, что происходит в его недрах. Пришло время это исправить: этот материал посвящён обзору JS-движка на примере V8, механизмов времени выполнения, и стека вызовов.

Обзор

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

Здесь мы поговорим, на довольно высоком уровне, о выполнении JS-кода. Зная о том, что, на самом деле, происходит при выполнении JavaScript, вы сможете писать более качественные программы, которые выполняются без «подвисаний» и разумно используют имеющиеся API.

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

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

Движок JavaScript

V8 от Google — это широко известный JS-движок. Он используется, например, в браузере Chrome и в Node.js. Вот как его, очень упрощённо, можно представить:

javascript время выполнения скрипта
Упрощённое представление движка V8

На нашей схеме движок представлен состоящим из двух основных компонентов:

Механизмы времени выполнения

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

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

Стек вызовов

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

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

Рассмотрим пример. Взгляните на следующий код:

Когда движок только начинает выполнять этот код, стек вызовов пуст. После этого происходит следующее:
javascript время выполнения скрипта
Стек вызовов в ходе выполнения программы

Каждая запись в стеке вызовов называется стековым кадром.

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

Если выполнить это в Chrome (предполагается, что код находится в файле foo.js ), мы увидим следующие сведения о стеке:

javascript время выполнения скрипта
Трассировка стека после возникновения ошибки

Если будет достигнут максимальный размер стека, возникнет так называемое переполнение стека. Произойти такое может довольно просто, например, при необдуманном использовании рекурсии. Взгляните на этот фрагмент кода:

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

javascript время выполнения скрипта
Превышение максимального размера стека вызовов

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

Однако, и у исполнения кода в однопоточном режиме тоже есть определённые ограничения. Учитывая то, что у JavaScript имеется один стек вызовов, поговорим о том, что происходит, когда программа «тормозит».

Параллельное выполнение кода и цикл событий

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

«А в чём тут проблема?», — спросите вы. Проблема заключается в том, что до тех пор, пока в стеке вызовов имеется выполняющаяся функция, браузер не может выполнять другие задачи — он оказывается заблокированным. Это означает, что браузер не может выводить ничего на экран, не может выполнять другой код. Он просто останавливается. Подобные эффекты, например, несовместимы с интерактивными интерфейсами.

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

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

Браузер предлагает завершить выполнение страницы

Пользователям подобные вещи точно не понравятся.

Итак, как же выполнять тяжёлые вычисления, не блокируя пользовательский интерфейс и не подвешивая браузер? Решение этой проблемы заключается в использовании асинхронных функций обратного вызова. Это — тема для отдельного разговора.

Итоги

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

Уважаемые читатели! Этот материал — первый в серии «How JavaScript Works» из блога SessionStack. Уже опубликован второй — посвящённый особенностям V8 и техникам оптимизации кода. Как по-вашему, стоит ли его переводить?

Источник

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

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