Skip to content

Instantly share code, notes, and snippets.

@Busyrev
Last active August 4, 2022 18:55
Show Gist options
  • Star 7 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save Busyrev/6c2eb1651a8df961c1e6552116235a27 to your computer and use it in GitHub Desktop.
Save Busyrev/6c2eb1651a8df961c1e6552116235a27 to your computer and use it in GitHub Desktop.
О сжатии на протокольном уровне (http)

О сжатии на протокольном уровне (http)

Актулизировано на момент 03.12.2018 Док несколько потерял в актуальности, см презентацию https://docs.google.com/presentation/d/1bw0ypsrdyC2l35Z-h65D09ABQDSZ_Ecfp02-zE6Fmqc Если кратко то brotli 0 в 4 раза быстрее чем gzip 1, при том же сжатии И brotli 4 столь же быстр как gzip 1 на круче чем gzip 9

Обозреваемые форматы сжатия:

  • gzip 1 - минимальный уровень сжатия gzip, результат .gz
  • gzip 9 - максимальный уровень сжатия gzip, результат .gz
  • zopfli - отдельный алгоритм совместимый с распаковщиком gzip, результат .gz
  • brotli 11 - полностью новый формат, 11 это максимальный уровень сжатия, результат .br

Не рассматривается - sdch(нет поддержки в современных браузерах), попытки запустить gzip > 1, zopfli, brotli на лету без пребилда сжатых файлов (для нас не актуально, очень много данных)

С точки зрения скорости сжатия:

  • gzip 1 - быстр, мало влияет на затраты cpu, но всё-же влияет
  • gzip 9 - медленнее примерно в 10 раз чем, gzip 1
  • zopfli - чудовищно медленный, в 20-50 раз медленнее чем gzip 9. Для примера Json на 16 мегабайт сжимался 273 секунды
  • brotli 11 - очень медленный, в 2-10 раз быстрее zopfli, но всё ещё на порядок медленне gzip 9.

С точки зрения качества сжатия:

  • gzip 1 - выигрыш от сырых данных 50-90%
  • gzip 9 - выигрыш от gzip 1 15-45%
  • zopfli - выигрыш от gzip 9 4-7%
  • brotli 11 - выигрыш от zopfli 8-65%

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

  • gzip 1 -
  • gzip 9 - примерно равен gzip 1
  • zopfli - примерно равен gzip 1
  • brotli 11 - быстрее примерно на 30% (по данным linkedin, я не тестил)

О сжатии на уровне HTTP

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

Особенности DevTools в хроме

При скачивании файла, в графе size будет указано непосредственно передаваемое по сети значение, т.е. запакованный размер. Чтобы понять с каким сжатем скачался этот файл, нужно включить отображение заголовка Content-Encoding из ответа сервера, правой кнопке по заголовку столбца, отметить флажком Responce Headers -> Content-Encoding, см картинку http://service.crazypanda.ru/v/clip2net/k/q/mo48yPT815.png

Как выбирается формат

Бразуер, умеющий работать со сжатыми данными, делая запрос указывает заголовок, например: Accept-Encoding: gzip, deflate, br. Веб сервер, который сконфигурирован на работу со сжатыми данными, смотрит на этот заголовок, и если он умеет отдавать один из форматов которые умеет принять браузер, то он выберет какой-то(тут вопрос к серверу, по идее должен выбирать тот что лучше сжимает, т.е. в порядке увеличесния степени сжатия deflate, gzip, br) и шлёт эти данные с указанием заголовка, например Content-Encoding: gzip по этому заголовку браузер понимает как распаковать данные. Если общего формата сжатия нет, то сервер отвечает беp Content-Encoding заголовка и просто отправляет сырые данные.

Про кеширование Nginx

Чтобы веб сервер отдал сжатый файл, он должен откуда-то его взять. Если просто включить gzip сжатие на Nginx то он будет каждый раз на лету сжимать его перед отправкой каждому клиенту. Он не кеширует сжатый результат по умолчанию. Если просто включить gzip on; то он будет сжимать только MIME type text/html и если вы хотите жать что-то ещё, то нужно отдельно настроить определение MIME type по расширению файла, а уже потом включить этот MIME type в категорию сжимаемых.

Про уровень сжатия на лету

По умолчанию Nginx сжимает gzip 1, это минимальный уровень, он быстр, и эффективен, даёт выигрыш в 2-10 раз (т.е. выигрыш по сжатию 50-90%), в зависимости от контента. При больших нагрузках даже deflate минимального уровня и gzip 1 могу обрушить всё, тщательно протестируйте и вонзайте только с полным пониманием того что вы делаете. Поднимать уровень сжатия на лету категорически не советую, т.к. выигрыш относительно первого уровня 10-45% (разов уже нет) при росте времени сжатия в 10 раз.

Про тип файла для сжатия

Не нужно сжимать те форматы которые уже сжаты, например png, jpg, swf, mp3, видео и тп. Сжатие уже сжатых форматов не полезно, а вредно, их размер незначительно увеличивается и добавлается нагрузка на распаковку. Вам необходимо выяснить какие форматы используются в вашем приложении и понять что нужно сжимать о что нет, наилучший способ - проверить руками и составить табличку(см внизу мою таблицу). Js файлы жмутся очень хорошо (brotli в 30 раз примерно ), в принципе выигрыш от сжатия больше чем от минификации. Для brotli минифицированная версия jquery позволяет выиграть ещё 30% по сравнению с jquery со стрипнутыми комментами но без минификации.

Про размер файла для сжатия

Все форматы при сжатии очень маленьких файлов дают накладные расходы или очень маленький выигрыш, сжимать стоит файлы от 5-10 килобайт. Меньше особо жать нет смысла. Например файл в 32 байта только вырастает в размере.

Особенности кеширования в nginx

Любое сильное сжатие стоит использовать с предсжатым файлом.

Для gzip есть static_gzip, это отдельный официальный модуль требующий перекомпиляцию nginx. Что примечательно он умеет gunzip, соответсвенно можно хранить только gzip версию и делать распаковку на лету для тех клиентов которые не умеют gzip.

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

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

Особенности поддержки в современных браузерах.

Все совеременные десктопные браузеры (Chrome, FireFox, Edge) с некоторых версий, поддерживают brotli. Подозреваю около 80-90% с его поддержкой. Незначительно количество браузеров поддерживают только gzip, и совсем экзотика и всякие прокси не поддерживают сжатие. Формат без сжатия надо всё-таки продолжать поддерживать.

Выводы

zopfli - в топку, brotli огонь, gzip 9 тоже неплох. Для продакшна только статик препакед.

Принятая схема распространения контента указана во внутренней документации компании. В все файлы dds проекта жмутся при помощи brotli в три раза

Для js файлов на фоне космического коэффициента сжатия brotli считаю ненужным минификацию.

Ссылки

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment