Pull to refresh

Улучшения в подсистеме кэширования Internet Explorer 9

Reading time8 min
Views4.1K
Original author: Internet Explorer Team
image
Сеть играет ключевую роль в общей производительности веб-браузера. Лучшим способом увеличить производительность работы с сетью является уменьшение объема трафика передаваемого по сети с помощью HTTP-сжатия и использования кэширования в браузере.

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

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


Давайте начнем с быстрого описания того, как работает кэширование в браузерах. На самом высоком уровне браузеры выполняют два типа запросов HTTP(S) – условные запросы и безусловные запросы.

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

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

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

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

Заголовки с экстремально большими значениями периода жизни


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

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

Улучшения параметра Vary


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

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

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

Мы можем безопасно поддерживать эти две директивы по следующим причинам:
  1. все запросы явно зависят от Host, потому что хост – это компонент URL запроса;
  2. IE всегда распаковывает HTTP-ответы в кэш, что делает Vary: Accept-Encoding избыточным.
Как и IE6 и выше, IE9 так же игнорирует директиву Vary: User-Agent.

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

Кэширование редиректов


IE9 теперь поддерживает кэширование ответов с HTTP-редиректом, как это описывается в RFC2616. Ответы с перманентным редиректом (со статусом 301) будут кэшироваться до тех пор пока они не содержат заголовки запрещающие это (например, Cache-Control: no-cache) и те запросы, которые имеют статус временный редирект (302 или 207) тоже будут кэшироваться, если заголовки позволят это (например, Cache-Control: max-age=120).

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

> GET / HTTP/1.1

< 301 Redirect to /SetCookie.asp


> GET /SetCookie.asp HTTP/1.1

< 301 Redirect to /


Здесь, цель сайта установить cookie с помощью вспомогательной страницы, если оно не установлено. Проблема в том, что сервер выбрал 301 для этой задачи и 301 – кэшируется. Как следствие, IE будет просто осуществлять редиректы на стороне клиента без обращения к серверу пока пользователю это не надоест и он не закроет браузер. Учтите, что этот бесконечный цикл будет и в том случае, если cookie запрещены в браузере пользователя.

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

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


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

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

Оптимизация функций Вперед/Назад


В IE9 мы сделали ряд улучшений для того, чтобы кнопки “Вперед” и “Назад” приводили к быстрой загрузке.

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

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

В предыдущих версиях IE, когда пользователь переходил вперед или назад, IE проверял обновление ресурсов, если они были посланы с директивой кэша must-revallidate и в зависимости от некоторых других параметров того, как ресурс был получен. В IE9 используется флаг INTERNET_FLAG_FWD_BACK и IE не будет проверять актуальность кэшированных ресурсов когда пользователь переходит по “вперед/назад”.

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

- 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 в прошлом или когда дата Expires не позже, чем значение заголовка Date. По этой причине, браузеру приходится перезагрузить такие ресурсы когда пользователь переходит “вперед/назад”. Для увеличения производительности и создания возможности загрузки ресурса в кэш при навигации вперед/назад, просто замените Cache-Control: no-cache на Cache-Control: max-age=0, в таком случае перевалидация будет происходить во всех случаях кроме навигации вперед/назад.

В отличии от других улучшений, которые мы описали, улучшение в работе “вперед/назад” нельзя наблюдать в превью-версии Internet Explorer 9 Platform Preview, поскольку в ней нет кнопок “впере/назад”.

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


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

IE позволяет пользователям конфигурировать что должно произойти с контентом, который получен без информации об истечении срока актуальности. В настройках Tools > Internet Options > Browsing history > Settings вы можете обнаружить четыре опции:

image

Эти опции предлагают следующее поведение:

Every time I visit the webpage
Ресурсы без явной информации о времени актуальности помечаются как устаревшие и будут перевалидированы с сервером перед каждым использованием
Every time I start Internet Explorer
Любой ресурс без явной информации о времени актуальности проводит валидацию с сервером по крайней мере один раз за сессию (и каждые 12 часов в этой сессии)
Automatically (Default)
IE будет использовать механизм эвристики для определения актуальности
Never
Любой кэшированный ресурс будет помечен как актуальный и не будет перевалидирован

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

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

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

max-age = (DownloadTime — LastModified) * 0.1

Если заголовок Last-Modified отсутствует в ответе сервера, тогда IE применит поведение перевалидации “Once per browser session” (один раз за сессию).

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

- IE8
IE9
Улучшение
Повторное посещение в новой сессии браузера (PLT2) Число запросов:

42

Байтов передано:

26050

Байтов получено:

220681
Число запросов:

2

Байтов передано:

1134

Байтов получено:

145217
Число запросов:

-40 (-95.3%)

Байтов передано:

-24916 (-95.6%)

Байтов получено:

-75464 (-34.2%)

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

image

Прочие улучшения в работе с сетью


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

В следующих статьях я опишу прочие улучшения, которые мы произвели в сетевом стеке IE9 для еще более быстрой загрузки страниц.
Tags:
Hubs:
+2
Comments32

Articles