Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Высокопроизводительный сетевой стек Chrome

Глава 1 из книги "Производительность приложений с открытым исходным кодом".

Оригинал: High Performance Networking in Chrome
Автор: Ilya Grigorik
Перевод: А.Панин

Оптимизация управления соединениями по протоколу TCP с помощью механизма предварительного соединения

Мы предварительно разрешили имя узла и приняли сигнал о высокой вероятности последующего наступления события перехода на страницу от строки ввода Omnibox или от предиктора Chrome. Почему бы не сделать шаг вперед и не установить предварительное соединение с удаленным узлом, выполнив рукопожатие TCP перед тем, как пользователь осуществит запрос? Выполнив эту операцию, мы можем избежать другой дополнительной задержки, вызванной обращением пакетов, в результате чего можем без лишних сложностей сэкономить сотни миллисекунд времени пользователя. То есть, следует воспользоваться техникой установления предварительного соединения по протоколу TCP и разобраться в принципе ее работы.

Для ознакомления с именами узлов, для которых была использована технология предварительного установления соединения по протоколу TCP, откройте новую вкладку и перейдите по адресу chrome://dns.

Вывод имен узлов, для которых была использована технология предварительного установления соединения по протоколу TCP
Рисунок 1.9 - Вывод имен узлов, для которых была использована технология предварительного установления соединения по протоколу TCP

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

Для заинтересованных лиц Chrome предоставляет утилиту по адресу chrome://net-internals#sockets для исследования состояния всех открытых в рамках Chrome сокетов. Снимок экрана представлен на Рисунке 1.10.

Открытые сокеты
Рисунок 1.10 - Открытые сокеты

Следует учесть и то, что вы также можете узнать подробности функционирования каждого из сокетов и исследовать его временные параметры: время соединения и установления связи с прокси-сервером, время доставки каждого из пакетов, а также дополнительные параметры. И не в последнюю очередь следует сказать о том, что вы также можете экспортировать эти данные для последующего анализа или создания сообщения об ошибке. Наличие хороших инструментов является важнейшим условием успешного выполнения оптимизаций производительности, а страница chrome://net-internals является порталом для всех параметров сетевого стека Chrome - если вы еще не изучили ее, самое время это сделать!

Оптимизация процесса загрузки ресурсов с помощью подсказок

Иногда автор страницы может предоставить возможность дополнительного перехода на страницу или дополнительный контекст страницы, базируясь на структуре своего сайта, и помочь браузеру оптимизировать свои пользовательские качества при просмотре страницы. Chrome поддерживает две применяемых в таких случаях подсказки, которые могут включаться в код разметки страницы:
 <link rel="subresource" href="/javascript/myapp.js">
 <link rel="prefetch"    href="/images/big.jpeg">

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

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

При корректном использовании обоих подсказок пользовательские качества браузера, используемого для просмотра вашего сайта, могут быть оптимизированы в значительной степени. Наконец, также важно учитывать тот факт, что директива "prefetch" является частью спецификации HTML5 и на сегодняшний день поддерживается браузерами Firefox и Chrome, в то время, как директива "subresource" на данный момент доступна только в Chrome.

Оптимизация процесса загрузки ресурсов с помощью технологии предварительного обновления ресурсов браузером

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

Однако, как мы увидели ранее, Chrome уже имеет возможность запоминать имена узлов для популярных ресурсов с целью выполнения предварительного разрешения имен этих узлов с использованием сервера DNS. И по какой причине мы не можем выполнить то же самое действие, но сделав один шаг вперед и выполнив разрешение имени узла с помощью сервера DNS, использовав технологию установления предварительного соединения по протоколу TCP, а также предварительно получив ресурс? Да, это именно то, что будет делаться в процессе предварительного обновления ресурсов (prefreshing):
  • Пользователь инициирует запрос с использованием строки URL для целевого ресурса
  • Chrome отправляет предиктору запрос на получение подресурсов, ассоциированных с данной строкой URL, после чего инициирует разрешение имен узлов с использованием сервера DNS, осуществляет предварительное соединение по протоколу TCP и выполняет предварительное обновление ресурсов
  • В том случае, если ассоциированный подресурс находится в кэше, он загружается с диска в память
  • В том случае, если ассоциированный подресурс отсутствует, выполняется сетевой запрос

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

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

Оптимизация переходов между страницами с помощью технологии предварительного вывода страниц

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

Конечно же, вы знаете ответ на этот вопрос, ведь это стандартная технология, применяемая многими пользователями: если вы откроете множество вкладок, то последующие переходы между вкладками будут осуществляться мгновенно и, безусловно, гораздо быстрее, чем в случае ожидания перехода на страницу одного и того же ресурса в одной открытой вкладке. И какой же API представлен браузером для этого?
 <link rel="prerender" href="http://example.org/index.html">

Как вы догадались, это директива предварительного вывода страницы для Chrome. Вместо простой загрузки отдельного ресурса, которая должна выполняться в случае использования директивы-подсказки "prefetch", директива "prerender" указывает Chrome на необходимость предварительного вывода страницы в скрытой вкладке вместе со всеми ее подресурсами. Сама скрытая вкладка невидима для пользователя, но когда он осуществляет переход на страницу, данные вкладки переносятся из невидимой вкладки для "мгновенного перехода" на страницу.

Хотите испробовать эту технологию? Вы можете посетить ресурс prerender-test.appspot.com и использовать реальный тест, а также просмотреть историю и состояние предварительно выведенных страниц для вашего профиля, перейдя по адресу chrome://net-internals/#prerender. (Обратитесь к Рисунку 1.11.)

Предварительно выведенные страницы для текущего профиля
Рисунок 1.11 - Предварительно выведенные страницы для текущего профиля

Как вы можете догадываться, полноценный вывод страницы в скрытой вкладке может потребовать больших затрат ресурсов, как центрального процессора, так и сетевого соединения, поэтому данная операция должна осуществляться исключительно в тех случаях, когда у нас есть очень веское предположение о том, что скрытая вкладка в конце концов будет использована. Например, в том случае, когда вы используете строку ввода Omnibox, процесс предварительного вывода страницы может быть запущен после отправки сообщения с наиболее вероятным предположением о переходе. Аналогично, поисковая система Google иногда добавляет директиву предварительного вывода страницы в код разметки страницы результатов поиска в том случае, когда, в соответствии с ее оценкой, первый результат запроса с высокой вероятностью будет результирующим направлением перехода (также эта техника известна как Google Instant Pages):

Следует помнить и о том, что вы также можете добавлять подсказки для предварительного вывода страниц на своем сайте. Перед началом работы нужно обратить внимание на тот факт, что техника предварительного вывода страниц имеет ряд запретов и ограничений, о которых следует знать:
  • Для всех процессов вывода страниц допустимо использование не более одной вкладки для предварительного вывода страниц
  • Использование протокола HTTPS одновременно с осуществлением аутентификации по протоколу HTTP недопустимо
  • Процесс предварительного вывода страницы прерывается в том случае, если для доступа к запрашиваемому ресурсу или какому-либо из его подресурсов требуется выполнение специальных запросов (допускается использование исключительно запросов GET)
  • Для трафика, генерируемого при получении всех ресурсов, устанавливается самый низкий приоритет
  • Для процесса вывода страницы также устанавливается самый низкий приоритет
  • Вывод страницы прекращается в том случае, если ее требования к оперативной памяти превышают ограничение в 100 Мб
  • Процесс инициализации плагинов откладывается, а предварительный вывод страницы прекращается в том случае, если она содержит мультимедийный элемент HTML5

Другими словами, выполнение предварительного вывода страницы не гарантируется и осуществляется только для тех страниц, которые могут быть безопасно загружены и выведены в фоновом режиме. В дополнение к этому, так как сценарии JavaScript и другие логические операции могут быть выполнены на скрытой странице, лучшим решением для установления того, является ли страница видимой, является использование API видимости страниц (Page Visibility API) - в любом случае вам придется это делать.

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

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

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


  1. Глава 10: Секреты производительности сетевого стека мобильных приложений описывает эту ситуацию в мельчайших подробностях.
  2. Если вас интересует этот вопрос, wiki проекта Chromium содержит замечательное описание.
  3. http://code.google.com/searchframe#OAMlx_jo-ck/src/content/public/browser/resource_dispatcher_host.h&exact_package=chromium&q=ResourceDispatcherHost.
  4. Данные ресурсов размером менее 16 КБ хранится в разделяемых на блоки файлах, а данные ресурсов большего размера хранятся отдельных файлах на диске.

Вернуться к началу статьи.