Швейцарские булочки (brötli). Фото @xeitgmbh из Instagram

Реальная эффективность Brotli

Artur Basak
11 min readNov 23, 2020

--

Это вольный перевод статьи Гарри Робертса из его блога CSS Wizardy.

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

Де-факто стандарт сжатия текста в Интернете — это Gzip (алгоритм Deflate), около 80% сжатых HTTP-ответов поддерживают этот алгоритм, а остальные 20% используют гораздо более новый алгоритм Brotli.

Само собой, сумма в 100% говорит только об HTTP-ответах, которые на самом деле были сжаты - все еще есть миллионы ресурсов веб-сайтов, которые могли бы или должны были бы быть сжаты, но не были. Для более подробной разбивки чисел см. Раздел "Compression" Web Almanac.

Gzip чрезвычайно эффективен. Все произведения Шекспира весят 5,3 МБ в текстовом формате; после сжатия Gzip (уровень сжатия 6) это число уменьшается до 1,9 МБ. Это уменьшение размера файла в 2,8 раза без потери данных. Это круто!

Еще лучше для нас то, что принцип работы алгоритма в Gzip основан на повторениях — чем больше повторяющихся строк находится в текстовом файле, тем более эффективным может быть сжатие. Это отличные новости для Интернета, где HTML, CSS и JS имеют очень последовательный и повторяющийся синтаксис.

Однако, несмотря на то, что Gzip очень эффективен, он также очень стар; он был выпущен в 1992 году (что, безусловно, помогает объяснить его повсеместное распространение). 21 год спустя, в 2013 году, Google презентовал новый алгоритм Brotli, который призван заменить Gzip! Тот же сборник Шекспира размером 5,2 МБ уменьшается до 1,7 МБ при сжатии с помощью Brotli (уровень сжатия 6), что дает уменьшение размера файла в 3,1 раза. Это определенно круче!

Используя программу Пола Кальвано Gzip and Brotli Compression Level Estimator!, вы, вероятно, обнаружите, что некоторые файлы могут быть значительно более экономны в своем размере, используя для сжатия Brotli вместо Gzip. ReactDOM, например, становится на 27% меньше при сжатии с использованием Brotli максимального уровня (11) по сравнению с Gzip и его максимальным уровнем (9).

На всех уровнях сжатия Brotli всегда превосходит Gzip. При максимальных настройках Brotli на 27% эффективнее Gzip. Сжатие библиотеки ReactDOM.

Перевод одного из моих клиентов с Gzip на Brotli привел к средней экономии размера файла на 31%.

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

Поддержка браузера: краткая интерлюдия. Хотя Gzip и настолько хорошо поддерживается, что Can I Use даже не перечисляет для него браузеры, ("Этот HTTP-заголовок поддерживается практически во всех браузерах (начиная с IE6 +, Firefox 2+, Chrome 1+ и т.д.)"), Brotli в настоящее время имеет 93,17% поддержку по всему миру на момент написания этой статьи, а это огромное покрытие! Тем не менее, обслуживание несжатыми ресурсами более чем 6% ваших клиентов может вам не понравиться. Что ж, это не проблема. Так как клиенты предоставляют информацию о поддержке определенного алгоритма в своих HTTP-запросах, это работает полностью прогрессивно, поэтому пользователи, которые не могут принять Brotli, просто получат ресурс сжатым Gzip. Подробнее об этом чуть позже.

Чаще всего, особенно если вы используете CDN, включение Brotli должно быть простым переключением какого-нибудь флага в настройках. Это точно очень просто в Cloudflare, через которую я запускаю CSS Wizardry. Однако некоторым моим клиентам за последние пару лет повезло меньше. У них либо была собственная инфраструктура, а установка и развертывание Brotli повсюду оказалось нетривиальной задачей, либо они использовали CDN, у которых не было готовой поддержки нового алгоритма.

В тех случаях, когда нам не удавалось включить Brotli, мы всегда задавались вопросом: “А что, если…”. Итак, наконец, я решил попытаться ответить на вопрос: насколько важно, чтобы мы переехали на Brotli?

Меньше не значит быстрее

Обычно да! Как правило, уменьшение размера файла приведет к тому, что он будет доставлен по сети быстрее. Но если сделать файл, скажем, на 20% меньше, он не появится на 20% раньше. Это связано с тем, что размер файла — это только один аспект веб-производительности, и каким бы ни был размер файла, загрузка ресурса будет по-прежнему зависеть от множества других факторов и констант — задержки сети (network latency), потери пакетов (packet loss) и т. д.

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

TCP, пакеты и круговая задержка

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

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

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

Для решения этой маленькой головоломки TCP использует механизм, известный как медленный старт. Каждое новое TCP-соединение ограничивается отправкой всего 10 пакетов данных за первый цикл приема-передачи. Десять сегментов TCP равняются примерно 14 КБ данных. Если эти десять сегментов будут доставлены успешно, в следующем цикле приема-передачи будет 20 пакетов, затем 40, 80, 160 и так далее. Этот экспоненциальный рост продолжается, пока не произойдет одно из двух:

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

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

Проще говоря: ваша начальная пропускная способность для нового TCP-соединения составляет всего около 14 КБ. Или примерно 11,8% несжатого ReactDOM; 36,94% сжатого Gzip ReactDOM; или 42,38% ReactDOM c Brotli(оба установлены на максимальное сжатие).

Погодите. Скачок с 11,8% до 36,94% довольно заметен! Но изменение с 36,94% до 42,38% гораздо менее впечатляющее. В чем же дело?

Обе версии ReactDOM, сжатые Gzip и Brotli, помещаются в одно и то же количество полетов туда и обратно: всего два цикла, чтобы получить полный файл. Если все значения времени приема-передачи (RTT) одинаковы, то это означает, что здесь нет разницы во времени передачи между Gzip и Brotli.

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

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

Это означает, что теоретически для того, чтобы Brotli был заметно более эффективным, чем Gzip, он должен иметь возможность сжимать файлы гораздо более агрессивно, чтобы переместить их ниже пороговых значений для двусторонней передачи. Я не уверен, насколько хорошо это будет…

Стоит отметить, что эта модель довольно сильно упрощена и есть множество других факторов, которые необходимо учитывать: является ли TCP-соединение новым или нет, используется ли оно для чего-то еще, является ли приоритезация на стороне сервера фактором прекращения передачи данных, имеют ли H/2 потоки эксклюзивный доступ к пропускной способности? Этот раздел представляет собой более академическую оценку и должен рассматриваться как хорошая отправная точка, однако, подумайте о том, чтобы проанализировать данные должным образом в чем-то вроде Wireshark, а также прочитайте гораздо более криминалистический анализ магии 14 КБ Барри Полларда в его статье Critical Resources and the First 14 КБ - Review.

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

  • Не то чтобы это нужно было повторять: вам нужно хостить свои статические ресурсы у себя на сервере. Это отличный способ избежать повторных медленных стартов, поскольку использование вашего собственного уже разогретого соединения означает, что ваши пакеты имеют доступ к большей пропускной способности сети, что подводит меня к пункту два;
  • С экспоненциальным ростом вы можете видеть, насколько быстро мы достигаем относительно высокой пропускной способности. Чем дольше мы используем или переиспользуем соединения, тем больше мы можем увеличивать пропускную способность, пока не достигнем максимума. Давайте взглянем на периодичность таблицы приведенной ниже…

К концу 10 циклов приема-передачи у нас будет пропускная способность TCP — 7 168 КБ , а сумма уже переданных данных — 14 322 КБ. Этого более чем достаточно для обычного просмотра веб-страниц (т. е. без торрента/стриминга Game of Thrones). На самом деле мы в конечном итоге загружаем всю веб-страницу и все ее подресурсы еще до того, как достигнем предела нашей пропускной способности. Иными словами, ваша оптоволоконная линия 1 Гбит/с не сделает вашу повседневную работу в Интернете намного быстрее, потому что большую часть ее вы даже не используете.

К 20 циклам туда и обратно мы теоретически достигнем емкости в 7,34 ГБ.

А как насчет реального мира?

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

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

Я взял для примера несколько сайтов, руководствуясь следующими их характеристиками:

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

С этими требованиями получился следующий список и я начал свое тестирование:

  • m.facebook.com
  • www.linkedin.com
  • www.insider.com
  • yandex.com
  • www.esedirect.co.uk
  • www.story.one
  • www.cdm-bedrijfskleding.nl
  • www.everlane.com

Я хотел, чтобы тест был простым, поэтому сфокусировался только на:

  • передача данных, и;
  • время первой отрисовки контента (First Contentful Paint/ FCP);
  • без сжатия;
  • с Gzip и;
  • с Brotli.

FCP воспринимается как реальный и достаточно универсальный показатель, который можно применить к любому веб-сайту, потому что то, для чего людям нужен сайт— это контент. Также, потому что так сказал Пол Кальвано, и он крайне умен: «Brotli, по моему опыту, имеет тенденцию делать FCP быстрее, особенно когда критически важный CSS / JS велик».

Запускаем тесты

Вот небольшой секрет. Многие исследования веб-производительности — не все, но многие — основаны не на улучшениях, а часто экстраполируются и выводятся из противоположного: замедления. Например, для BBC гораздо проще сказать, что “они теряют дополнительно 10% пользователей за каждую дополнительную секунду, необходимую для загрузки их сайта”, чем выяснить, что происходит при ускорении на 1 секунду. Намного проще сделать сайт медленнее, поэтому так много людей кажутся хороши в этом.

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

Хотя я и не могу перейти на серверы LinkedIn и отключить Brotli, вместо этого я могу запросить сайт из браузера, который не поддерживает Brotli. Я не могу точно отключить Brotli в Chrome, но я могу скрыть от сервера тот факт, что Brotli поддерживается браузером. Браузер показывает какие алгоритмы сжатия он поддерживает через заголовок HTTP-запроса content-encoding, а с помощью WebPageTest я могу переопределить это значение. Легко!

Расширенная функция WebPageTest позволяет нам устанавливать собственные заголовки запросов.
  • Чтобы полностью отключить сжатие: accept-encoding: randomstring.
  • Чтобы отключить Brotli, но вместо этого использовать Gzip: accept-encoding: gzip.
  • Чтобы использовать Brotli, если он доступен (и браузер его поддерживает): оставьте поле пустым.

Затем я могу убедиться, что все работает, как планировалось, проверив соответствующий (или отсутствующий) заголовок кодирования содержимого content-encoding в HTTP-ответе.

Результаты

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

  • Уменьшение размера с Gzip по сравнению с его отсутствием: уменьшение на 73%
  • Улучшение FCP с Gzip по сравнению с его отсутствием: снижение на 23,305%
  • Уменьшение размера с Brotli по сравнению с Gzip: уменьшение на 5,767%
  • Улучшение FCP с Brotli по сравнению с Gzip: снижение на 3,462%

Все значения являются средними; “размер“ относится только к файлам HTML, CSS и JS.

Gzip сделал файлы на 72% меньше, в сравнении со случаем, когда мы их вообще не сжимаем, Brotli сэкономил нам только 5,7% сверх этого. Что касается FCP, Gzip дал нам улучшение на 23%, Brotli же принес нам только дополнительные 3,5% к этому.

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

Собственные ресурсы против сторонних

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

Уровни сжатия

Когда мы говорим о сжатии, мы часто обсуждаем его с точки зрения лучших сценариев: Gzip уровня 9 и Brotli уровня 11. Однако маловероятно, что ваш веб-сервер настроен наиболее оптимальным образом. По умолчанию уровень сжатия Gzip в Apache равен 6, а для Nginx установлен только 1.

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

Уровни сжатия — это всегда компромисс. В идеале вы хотели бы установить все на максимальное значение, но это не совсем практично — время, затрачиваемое сервером на то, чтобы сделать это динамически, вероятно, в первую очередь свело бы на нет преимущества самого сжатия. Чтобы с этим бороться, у нас есть два варианта:

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

Так и что?

Кажется, реальное преимущество Brotli перед Gzip невелико.

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

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

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

Полагаю, вкратце история в том, что если вы не включили или не можете включить Brotli, то вы многое не теряете.

P.S. от переводчика

На платформе Tispr, перейдя с Gzip (gzip_comp_level 9) на Brotli (brotli_comp_level 6) общий размер загружаемых файлов (HTML, CSS, JS и шрифты) уменьшился на 10%, а время полной загрузки на 3%, Total Blocking Time на 0,2 секунды, Largest Contentful Paint на 0,1 секунду, FCP без изменений. Тестирование проводилось на одной из новых фич платформы — Формах — с помощью WebPageTest.

--

--