Улучшение кэширования в Internet Explorer 9

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

Мы провели множество улучшений кэша в Internet Explorer 9, чтобы из него можно было загружать больше ресурсов. Это сообщение описывает усовершенствования, доступные в третьем выпуске IE9 Platform Preview, который вышел в прошлом месяце.

Суть кэширования

Давайте вспомним, как работает кэширование в браузере. На высоком уровне веб-браузеры делают два типа запросов по HTTP и HTTPS – условные и безусловные.

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

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

Если ответ в кэше устарел (превышено время max-age или прошел момент Expires), то клиент выполнит условный запрос к серверу, чтобы определить, является ли ранее сохраненный ответ актуальным, или запрос надо повторить. Условный запрос содержит заголовок If-Modified-Since и/или If-None-Match, который указывает серверу, какая версия содержимого кэша находится у браузера. Сервер может указать, что версия клиента еще актуальна, вернув в ответ заголовок HTTP/304 Not Modified без тела, или же он может указать, что версия клиента устарела, вернув ответ HTTP/200 OK с новой версией содержимого.

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

Крайне долгоживущие заголовки кэша

Хотя RFC 2616 рекомендует, чтобы сервер ограничивал срок годности контента периодом в один год, некоторые серверы отправляют директивы Cache-Control с указанием значительно больших промежутков времени. До версии IE9 Internet Explorer рассматривал бы в качестве устаревшего, ресурс со временем жизни Cache-Control:max-age, превышающем 2147483648 (2^31) секунд, что соответствует примерно 68 годам.

В Internet Explorer 9 мы теперь принимаем любое значение до 2^63 для максимального возраста, хотя внутренний срок актуальности будет обрезан до 2^31 секунд.

Улучшения директивы Vary

Заголовок ответа сервера HTTP/1.1 Vary позволяет установить, что актуальный кэшируемый ресурс подходит для будущего повторного использования без повторного подтверждения сервера, только если указанные заголовки запроса в последующих запросах соответствуют заголовкам оригинального запроса.

Например, это позволяет серверу возвращать содержимое на английском языке с заголовком Vary: Accept-Language. Если пользователь в последующем изменит Accept-Language в браузере с EN-US на JA-JP, находящееся в кэше содержимое не будет использоваться повторно, так как заголовок Accept-Language не соответствует заголовку первоначального запроса, в то время, как в кэше содержится оригинальный английский ответ.

В Internet Explorer 9 мы расширили поддержку сценариев ключевых вариантов заголовка. В частности, IE9 больше не будет требовать повторного подтверждения сервера для ответов, которые содержат директивы Vary: Accept-Encoding и Vary: Host.

Мы можем с уверенностью поддержать эти две директивы, потому что:

  • Все запросы неявно зависят от Host, потому что host – один из компонентов запроса URL.
  • IE всегда распаковывает HTTP ответы в кэш-памяти, что делает Vary: Accept-Encoding излишним.

Подобно IE6 и последующим версиям, IE9 будет игнорировать директиву Vary : User-Agent.

Если ответ содержит директиву Vary с заголовком, отличным от Accept-Encoding, Host, или User-Agent (или любой комбинации из них), то Internet Explorer будет по-прежнему кэшировать ответ, если ответ содержит заголовок ETAG. Однако этот ответ будет рассматриваться как устаревший и будет выполнен условный запрос HTTP перед повторным использованием, чтобы определить, действительна ли сохраненная копия.

Перенаправление кэширования

Internet Explorer 9 теперь поддерживает кэширование перенаправляющих ответов HTTP, как это описано в RFC 2616. Ответы с постоянными статусами переадресации (301) являются кэшируемыми, если нет запрещающих заголовков (например, Cache-Control: no-cache). Также кешируются ответы со статусом временной переадресации (302 или 307), если имеются заголовки, которые допускают его (например, Cache-Control: max-age=120).

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

> GET / HTTP/1.1

< 301 Redirect to /SetCookie.asp

> GET /SetCookie.asp HTTP/1.1

< 301 Redirect to /

Целью является определение, имеет ли пользователь набор cookie, а если нет, отправка его на страницу, которая устанавливает cookie. Проблема в том, что сервер выбрал ответ 301 для выполнения этих задач, а 301-й ответ кешируется. Таким образом, IE будет просто переключаться между этими двумя кэшируемыми перенаправлениями на клиенте (никогда не обращаясь к серверу), пока пользователю не надоест, и он не закроет браузер. Примечательно, что любая версия IE удалит циклические перенаправления в сценарии выше, если у пользователя отключено хранение cookie для данного сайта.

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

Улучшения кэширования HTTPS

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

Сейчас в IE9 ненужные кросс-хостовые HTTPS-запросы являются условными, так что сервер может просто вернуть ответ HTTP/304 Not Modified для неизменившегося содержимого.

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

Оптимизация Back/Forward

Мы внесли некоторые усовершенствования в IE9, чтобы отработка нажатия кнопок Back/Forward проходила более оперативно.

RFC 2616 особенно отмечается, что механизмы Back/Forward браузера не подпадают под директивы кэширования:

Механизмы истории и кэширования разные. В частности, механизмы истории НЕ ДОЛЖНЫ пытаться показать семантически прозрачное представление текущего состояния ресурса. Скорее механизм истории предназначен для точного показа того, что пользователь увидел в момент, когда ресурс был получен.

По умолчанию, понятие истечения времени не применимо к механизмам истории. Если некая сущность все еще находится в хранилище, механизм истории ДОЛЖЕН показать ее, даже если она уже не актуальна, разве только пользователь не настроил агента на обновление истекших документов в истории.

В предыдущих версиях Internet Explorer, когда пользователь перемещался с помощью кнопок Back/Forward, IE проверял актуальность ресурсов в том случае, если они были посланы с директивой управления кэша must-revalidate, а также в ряде других обстоятельств, зависящих от того, как давно ресурс был загружен. В IE9 флаг INTERNET_FLAG_FWD_BACK ведет себя, как описано в MSDN, а IE не будет проверять актуальность кэшированного ресурса, когда пользователь переходит вперед или назад.

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

 

IE8

IE9

Улучшение

Переходы вперед и назад

Счетчик запросов: 21

Послано байт: 12,475

Получено байт: 216,580

Счетчик запросов: 1

Послано байт: 325

Получено байт: 144,617

Счетчик запросов: -20 (-95%)

Послано байт: -12,150 (-97.4%)

Получено байт:-71,963 (-33.3%)

Как я уже упоминал, мы игнорируем директивы кэширования при навигации вперед и назад, и внимательные читатели могут удивиться, почему IE9 делает один запрос при нажатии кнопки «Назад» на этом сайте. Причина в том, что IE не помещает в кэш любые некэшируемые ресурсы. Некэшируемым является ресурс, который поставляться с директивой Cache-Control: no-cache или с датой Expires, которая истекла в прошлом или не превышает заголовка Date. Таким образом, браузер вынужден перезагрузить такие ресурсы, когда пользователь перемещается назад и вперед. Чтобы улучшить производительность и позволить повторно использовать ресурс при навигации «Вперед/Назад», сохраняя требование перепроверки для других целей, просто замените директиву Cache-Control: no-cache на Cache-Control: max-age=0.

В отличие от других улучшений, описанных в этой статье, оптимизация кнопок «Вперед/Назад» не видна в Platform Preview, поскольку последняя не имеет кнопки «Назад».

Эвристические улучшения кэша

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

Internet Explorer позволяет пользователю настроить, что должно произойти, когда содержание поставляется без предельного срока годности информации. Пройдя по пути Сервис> Свойства обозревателя> Журнал> Настройки, вы увидите четыре варианта:

clip_image001

Эти четыре варианта задают следующие поведения:

Каждый раз, когда я посещаю страницу

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

Каждый раз, когда я запускаю Internet Explorer

Любой ресурс, у которого не указана информация о сроке годности, проверяется на сервере, по крайней мере, один раз за сессию браузера (и каждые последующие 12 часов в этой сессии).

Автоматически (по умолчанию)

Для определения актуальности Internet Explorer использует эвристический алгоритм.

Никогда

Любые кэшированные ресурсы считаются актуальными и не будут перепроверяться.

Эти параметры контроля поведения браузера работают только тогда, когда содержимое поставляется без информации об истечении срока годности; если же содержимое имеет четкую политику (т.е., Cache-Control: max-age=3600 или Cache-Control: no-cache), то браузер будет следовать директивам сервера и варианты здесь не действуют.

В более ранних версиях IE автоматическая эвристика была проста и влияла только на кэшированные изображения, но IE9 улучшил эвристику, чтобы соответствовать предложенному в RFC 2616 поведению:

Если ответ поступает со временем Last-Modified, то эвристическое значение срока годности должны быть не больше некоторой части периода времени, протекшего с этого момента. Типичное значение этой части может составлять 10%.

Если Internet Explorer 9 получает кэшируемый ресурс, который явно не указывает свою актуальность, эвристический срок годности рассчитывается следующим образом:

max-age = (DownloadTime – LastModified) * 0,1

Если заголовка Last-Modified не было в ответе сервера, то Internet Explorer перейдет на алгоритм перепроверки «Один раз на сессию браузера».

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

 

IE8

IE9

Улучшение

Новое посещение в новом сеансе (PLT2)

Счетчик запросов: 42

Послано байт: 26 050

Получено байт: 220 681

Счетчик запросов: 2

Послано байт: 1 134

Получено байт: 145 217

Счетчик запросов: -40 (-95.3%)

Послано байт: -24 916 (-95.6%)

Получено байт: -75,464 (-34.2%)

Инспектор кэширования программы Fiddler покажет вам, когда истекает время жизни ответа, основываясь на его заголовке. Например, вот что вы видите в качестве ответа, содержащего заголовки ETAG и Last-Modified, но не имеющего информации о дате истечения:

clip_image002

Другие сетевые усовершенствования

В этом сообщении я перечислил улучшения в алгоритмах кэширования Internet Explorer, которые помогают обеспечить работу веб-сайтов и могут сделать как можно более эффективным использования сети. Конечно, веб-разработчики должны продолжать следовать установившимся практикам и указывать желаемое поведение кэша, используя заголовки Expires и Cache-Control, но даже сайты, которые не в состоянии сделать это будут загружаться в IE9 быстрее.

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

Эрик Лоуренс (Eric Lawrence)