Статьи

Понимание производительности браузера

Что такое производительность?

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

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

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

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

Web Runtime Architecture

Полная архитектура

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

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

сеть

Первое, что происходит, это сеть. Сеть начинается при первом вводе URL. Сейчас я буду говорить о начале с HTML-страницы, но реальность такова, что сеть обрабатывает любой тип ресурса, на который ссылается страница, включая XML, JSON, IMG, PDF и т. Д., И различные подсистемы вступают в игру для различных ресурсов. ,

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

Это важно, потому что браузер должен иметь под рукой весь ссылочный контент как можно быстрее, потому что все это взаимозависимо; HTML опирается на CSS и JavaScript, JavaScript может общаться только с DOM, который построен из HTML, и CSS не имеет ничего для стиля без HTML DOM, которым JavaScript может манипулировать. Да, это немного сбивает с толку, но, надеюсь, в скором времени здесь будет больше смысла.

сеть

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

Это на самом деле с того места, где началась спецификация, которая состояла из двух одновременных соединений! Причина этого ограничения заключается в том, чтобы помочь серверу обнаружить атаку типа «отказ в обслуживании» (DOS или DDOS), когда клиент открывает максимально возможное количество соединений и получает от сервера столько пропускной способности, сколько возможно. Хорошая новость о шести лимитах заключается в том, что он позволяет браузеру одновременно получать больше контента.

Подавляющее большинство веб-сайтов, которые я вижу, содержат весь контент с одного и того же сайта. Рекомендуется разделять эти ресурсы по разным доменам при наличии множества изображений, CSS, JavaScript или других ресурсов. Это один из самых быстрых способов использования CDN (Content Delivery Network). По этой же причине имеет смысл использовать размещенную версию распространенных JavaScript-фреймворков, а не размещать ее на своем собственном сервере.

Парсеры

Как только элемент загружен, он переходит к анализаторам. Существуют десятки разборов, которые разбирают все, включая, но не ограничиваясь, HTML, CSS, XML, XHTML, SVG, JavaScript и различные варианты. Работа парсеров заключается в создании внутренних структур данных, которые браузер будет использовать для остальной части обработки.

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

Внутренние структуры данных

Существует несколько различных внутренних структур данных, которые необходимы браузеру для выполнения своих задач. Самым известным из них является DOM (объектная модель документа). Если вы ранее занимались программированием JavaScript на веб-сайте, вы, вероятно, взаимодействовали с DOM на каком-то уровне. Общая мысль состоит в том, что DOM медленный и болезненный. Реальность — это нечто более сложное.

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

Другая очень важная структура для понимания — это CSS Cascade. Это объединение всех правил CSS, на которые имеются ссылки в HTML, и всех файлов CSS, а также правил, которые программно устанавливаются JavaScript. Он включает в себя все порядки приоритета относительно того, что переопределяет то, что и так далее.

JavaScript

JavaScript

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

Скорее, это безопасно, потому что у JavaScript есть только два выхода из песочницы — вызвать DOM API или вызвать сеть через XHR-запросы. Существует множество фреймворков, которые помогают решить обе эти задачи — jQuery — одна из самых популярных. Синтаксис $(“path statement”) Метод $.getJSON()

Styling — Форматирование и Макет

Следующий шаг, стилизация, фактически охватывает две подсистемы.

Первая подсистема стилей — это форматирование. Форматирование важно, потому что дерево DOM совершенно не знает ничего визуального. Все, что он знает, это родительские дочерние отношения между элементами и атрибутами. Это каскад CSS, который знает всю эту информацию. Во время форматирования эта информация объединяется, давая размер элементов DOM, цвет, фоны, размеры шрифта и так далее.

В конце этой подсистемы каждый отдельный элемент знает, как он выглядит.

Следующим шагом, теперь, когда все элементы DOM знают, как они выглядят, является выяснение того, как они выглядят вместе на странице — это процесс макета.

CSS

CSS по своей сути является блочным макетом. Это означает, что все; изображения, абзацы, div, span, формы событий, такие как круги, фактически являются блоками для CSS. Большой вопрос, насколько большой блок. А HTML / CSS по своей сути является макетом, основанным на потоке, если что-то не отменяет этого. Это означает, что контент по умолчанию будет перемещаться в следующий доступный верхний правый угол, в который он помещается.

Поэтому, если ваш экран имеет ширину 800px, и у вас есть четыре элемента шириной 300px каждый, вы поместите два по верху, а третий перейдет к следующему ряду элементов. Однако CSS Cascade может переопределить это и позиционировать элементы в относительном или абсолютном порядке. Если он реляционный, его положение определяется определенным расстоянием от предыдущего элемента, который был выложен на экране.

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

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

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

В дереве DOM есть вещи, которых нет в дереве отображения, такие как элементы display: none или поля ввода type = hidden. Есть также вещи, которые находятся в дереве отображения, которых нет в дереве DOM, такие как числа в упорядоченном списке ( <ol><li>asdf</li></ol>

Краска и композитинг

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

Это означает, что на большинстве мониторов между обновлениями оно составляет 1000/60 (миллисекунды, деленные на частоту обновления), что составляет 16,67 миллисекунды (примерно). Это не так много времени, но на самом деле современный процессор I7 может выполнять примерно 2138333333 инструкций (миллионы инструкций в секунду, как отмечено в Википедии по инструкциям в секунду / 60). Между мной и тобой много инструкций.

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

Когда монитор готов к рисованию, он посылает аппаратное прерывание, которое запускает цикл рисования. На этом этапе браузер рисует слои страницы на поверхности, которая для IE представляет собой поверхности DirectX, которые компонуются и отображаются на мониторе для удобства пользователя с помощью диспетчера рабочего стола Windows (DWM).

взаимодействие

В этот момент браузер показал что-то на экране, так что это время загрузки. Тем не менее, пока нет анимации или какого-либо взаимодействия.

вход

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

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

Это то, что я имел в виду ранее, когда говорил, что описать DOM как «медленный» сложно. Дело не в том, что манипулирование DOM само по себе особенно медленное. Что медленно, так это то, что прикосновение к нему создает эффект домино, заставляя другие подсистемы срабатывать.

Резюме Web Runtime Architecture

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

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