Сжатие текста уже давно стало стандартом в мире веб‑приложений. Сокращение объёма данных даёт сокращение времени передачи и снижение нагрузки на сетевой канал. Однако, часто настройка компрессии сводится к динамическому сжатию gzip и настройкам по умолчанию. В этой статье разберём вопрос сжатия более глубоко. Для начала вспомним основные технологии сжатия, доступные в вебе.
Навигация по циклу
Настройка location в Angie. Разделение динамических и статических запросов.
Перенаправления в Angie: return, rewrite и примеры их применения.
Сжатие текста в Angie: статика, динамика, производительность.
Тест современных компрессоров для HTTP.
Видеоверсия
Для вашего удобства подготовлена видеоверсия этой статьи, доступна на Rutube, VKVideo и YouTube.
Варианты компрессии для веба
Для решения задачи сжатия текстовых ресурсов существует несколько форматов, получивших достаточно широкую поддержку в браузерах и других клиентах:
gzip, deflate— традиционный формат сжатия с максимальной поддержкой;brotli (br)— новый формат сжатия, оптимизирован для высоких коэффициентов компрессии;Zstandard (zstd)— новый формат, оптимизирован для высокой скорости сжатия и декомпрессии.
В контексте веб‑сервера Angie доступен штатный модуль для gzip и сторонние модули для brotli и zstd. Помимо алгоритмов сжатия есть два режима: динамический и статический. Динамическое сжатие означает компрессию ответа в реальном времени, во время обработки запроса. В таком режиме ресурсы процессора затрачиваются на каждый запрос. Статическое сжатие — это создание сжатых копий ресурсов на диске, которые при ответе нужно всего лишь прочитать с диска и отправить по сети. Таким образом, ресурс центрального процессора используется лишь один раз (при создании сжатой копии) и не во время обработки запроса, а при публикации ресурса (или сборки статики).
Выбор настроек для статического сжатия несложен: используем максимальные настройки компрессии (затраты процессорной мощности не важны) и формат, который обладает лучшим коэффициентом сжатия. Забегая вперёд, это будет brotli со степенью сжатия 11 (максимальная). Конечно, статическое сжатие стоит использовать везде, где это возможно. Также не стоит забывать про технику минификации файлов, где она применима. Использование минификации имеет положительный эффект на размер файла даже при использовании сжатия.
При использовании динамического сжатия выбор алгоритма сжатия и настроек компрессии не так очевиден. Сделать такой выбор нам поможет сравнительный тест.
Тестирование компрессоров
Ранее мы уже обращались к теме компрессоров для веба в статье про сжатие текстовых ресурсов. Основной акцент той статьи был на практике применения модулей сжатия в Angie. Сейчас стоит вернуться к вопросу выбора оптимальной степени сжатия и компрессора с учётом издержек на передачу, сжатие и декомпрессию текстового ресурса. Чтобы сделать обоснованный выбор, необходимо сравнить различные компрессоры в одинаковых условиях на наборе данных, приближённых к реальным.
В качестве бенчмарка будем использовать открытый проект lzbench. Он позволяет удобно сравнить скорость работы всех интересующих нас вариантов (brotli, zstd, gzip) и предоставляет результаты в удобной форме. В качестве тестовых данных будем использовать файлы с HTML, CSS и JS‑кодом большого размера (от 1 МБ и больше). HTML‑файл использован из комплекта Silesia (файл webster, 40,5 МБ). CSS и JS файлы взяты с реального сайта и имеют размеры 1,0 МБ и 1,8 МБ соответственно. Бенчмарк lzbench даёт высокую повторяемость результатов и использует актуальные версии библиотек. Результаты хорошо согласуются с тестированием модулей сжатия в сервере Angie. Бенчмарк всегда использует одно ядро процессора, что также нас устраивает. При этом процессор обладает высокой тактовой частотой, поэтому на серверных системах стоит ожидать более низких абсолютных показателей.
Условия тестирования:
lzbenchактуальной версии (сборка из исходных кодов);zlib 1.3.1;brotli 1.2.0;zstd 1.5.7;ЦПУ: AMD Ryzen 5800x;
ОС: Ubuntu 24.04.
Виртуализация: KVM.
Запуск тестов производился следующей командой (изменялся только файл):
./lzbench -o4 -ezlib/brotli/zstd 1.css
В параметрах мы запросили тест трёх интересующих нас библиотек и активировали формат вывода в CSV для простого импорта в электронную таблицу, где будет проводиться анализ. На выходе мы получаем три набора данных (каждый для своего файла), которые необходимо проанализировать. Исходные файлы и результаты можно найти репозитории.
Результаты теста
Первый тест проведён с файлом в формате HTML webster (40,5 МБ). В первой колонке указан компрессор, его версия и степень сжатия. Вторая колонка показывает скорость сжатия контента в МБ/c, третья — скорость декомпрессии. Четвёртая колонка отвечает за результирующий коэффициент сжатия в процентах от исходного объёма файла. Изучим таблицу подробнее.
Compressor name/level |
Compression speed (MB/s) |
Decompression speed (MB/s) |
Ratio (%) |
zlib 1.3.1 -1 |
141,53 |
469,47 |
36,16 |
zlib 1.3.1 -2 |
124,57 |
489,41 |
34,37 |
zlib 1.3.1 -3 |
91,49 |
508,62 |
32,87 |
zlib 1.3.1 -4 |
82,58 |
485,64 |
31,36 |
zlib 1.3.1 -5 |
55,63 |
483,93 |
30,02 |
zlib 1.3.1 -6 |
37,88 |
496,23 |
29,46 |
zlib 1.3.1 -7 |
30,07 |
499,30 |
29,26 |
zlib 1.3.1 -8 |
22,15 |
499,57 |
29,12 |
zlib 1.3.1 -9 |
22,35 |
498,03 |
29,12 |
brotli 1.2.0 -0 |
390,89 |
477,73 |
35,12 |
brotli 1.2.0 -1 |
261,08 |
500,91 |
32,47 |
brotli 1.2.0 -2 |
159,45 |
577,52 |
30,54 |
brotli 1.2.0 -3 |
134,31 |
591,11 |
29,95 |
brotli 1.2.0 -4 |
96,70 |
710,89 |
26,51 |
brotli 1.2.0 -5 |
64,60 |
722,73 |
25,57 |
brotli 1.2.0 -6 |
51,59 |
750,83 |
24,81 |
brotli 1.2.0 -7 |
32,91 |
767,46 |
24,18 |
brotli 1.2.0 -8 |
23,35 |
783,15 |
23,74 |
brotli 1.2.0 -9 |
16,98 |
783,95 |
23,42 |
brotli 1.2.0 -10 |
2,01 |
667,99 |
21,53 |
brotli 1.2.0 -11 |
0,86 |
780,11 |
21,20 |
zstd 1.5.7 -1 |
461,38 |
1 741,48 |
32,95 |
zstd 1.5.7 -2 |
340,35 |
1 487,24 |
30,89 |
zstd 1.5.7 -3 |
256,96 |
1 442,12 |
29,18 |
zstd 1.5.7 -4 |
251,40 |
1 408,85 |
28,72 |
zstd 1.5.7 -5 |
155,57 |
1 441,32 |
27,05 |
zstd 1.5.7 -6 |
108,97 |
1 562,15 |
26,07 |
zstd 1.5.7 -7 |
94,76 |
1 590,28 |
25,46 |
zstd 1.5.7 -8 |
72,15 |
1 665,88 |
25,13 |
zstd 1.5.7 -9 |
68,14 |
1 668,06 |
24,74 |
zstd 1.5.7 -10 |
49,19 |
1 697,94 |
24,26 |
zstd 1.5.7 -11 |
33,73 |
1 728,61 |
23,97 |
zstd 1.5.7 -12 |
30,87 |
1 727,13 |
23,92 |
zstd 1.5.7 -13 |
12,44 |
1 743,87 |
23,74 |
zstd 1.5.7 -14 |
10,61 |
1 771,26 |
23,39 |
zstd 1.5.7 -15 |
6,92 |
1 768,72 |
23,04 |
zstd 1.5.7 -16 |
5,83 |
1 718,46 |
22,10 |
zstd 1.5.7 -17 |
4,24 |
1 715,33 |
21,54 |
zstd 1.5.7 -18 |
3,16 |
1 698,01 |
21,23 |
zstd 1.5.7 -19 |
2,79 |
1 677,18 |
20,93 |
zstd 1.5.7 -20 |
2,35 |
1 397,29 |
20,45 |
zstd 1.5.7 -21 |
2,27 |
1 407,57 |
20,34 |
zstd 1.5.7 -22 |
2,20 |
1 384,54 |
20,34 |
Таблица 1. Результаты теста для HTML.
Абсолютный лидер по скорости компрессии: zstd -1, за ним идёт brotli -0. При этом zstd с низкими настройками компрессии достигает хорошего коэффициента. В целом по результатам zlib (gzip) показывает полный провал: как по скорости, так и по степени сжатия. Высокие настройки сжатия для brotli (10–11) и zstd (14–22) однозначно не пригодны для динамического сжатия из‑за низкой скорости. Что касается декомпрессии, то она практически не меняется в рамках одной библиотеки и остаётся стабильно высокой, абсолютный лидер в этой категории — zstd. Стоит заметить, что скорее всего задачей декомпрессии ресурса будет заниматься клиент и используемая библиотека может отличаться.
Если рассматривать результаты для статической компрессии, то здесь нас ожидает сюрприз: победителем выходит zstd -22. Обычно в этой категории побеждает brotli, но для этого файла большого размера (более 40 МБ) лучшим оказался zstd.
Посмотрим, будет ли отличаться картина при сжатии CSS.
Compressor name/level |
Compression speed (MB/s) |
Decompression speed (MB/s) |
Ratio (%) |
zlib 1.3.1 -1 |
101,35 |
507,15 |
39,58 |
zlib 1.3.1 -2 |
97,59 |
516,27 |
38,84 |
zlib 1.3.1 -3 |
91,37 |
527,28 |
38,33 |
zlib 1.3.1 -4 |
75,97 |
590,57 |
36,61 |
zlib 1.3.1 -5 |
67,64 |
600,61 |
35,97 |
zlib 1.3.1 -6 |
56,54 |
608,52 |
35,74 |
zlib 1.3.1 -7 |
51,55 |
607,71 |
35,68 |
zlib 1.3.1 -8 |
44,51 |
608,58 |
35,67 |
zlib 1.3.1 -9 |
44,06 |
607,95 |
35,67 |
brotli 1.2.0 -0 |
648,31 |
694,81 |
39,11 |
brotli 1.2.0 -1 |
511,76 |
716,54 |
37,66 |
brotli 1.2.0 -2 |
295,42 |
734,87 |
36,57 |
brotli 1.2.0 -3 |
257,88 |
766,68 |
36,02 |
brotli 1.2.0 -4 |
192,31 |
801,25 |
35,47 |
brotli 1.2.0 -5 |
130,44 |
814,85 |
34,67 |
brotli 1.2.0 -6 |
115,28 |
826,24 |
34,43 |
brotli 1.2.0 -7 |
95,35 |
834,93 |
34,24 |
brotli 1.2.0 -8 |
78,68 |
840,74 |
34,12 |
brotli 1.2.0 -9 |
33,36 |
842,3 |
34,04 |
brotli 1.2.0 -10 |
2,75 |
458,94 |
33,16 |
brotli 1.2.0 -11 |
1,08 |
466 |
33,02 |
zstd 1.5.7 -1 |
832,85 |
1777,62 |
38,31 |
zstd 1.5.7 -2 |
739,07 |
1686,06 |
37,46 |
zstd 1.5.7 -3 |
632,15 |
1702,85 |
36,29 |
zstd 1.5.7 -4 |
610,81 |
1679,72 |
36,28 |
zstd 1.5.7 -5 |
292,53 |
1819,12 |
35,13 |
zstd 1.5.7 -6 |
226,18 |
1877,61 |
34,73 |
zstd 1.5.7 -7 |
204,83 |
1923,58 |
34,53 |
zstd 1.5.7 -8 |
166,53 |
1945,69 |
34,43 |
zstd 1.5.7 -9 |
161,21 |
1946,21 |
34,42 |
zstd 1.5.7 -10 |
136,01 |
1980,51 |
34,29 |
zstd 1.5.7 -11 |
96,99 |
1968,38 |
34,19 |
zstd 1.5.7 -12 |
99,46 |
1966,44 |
34,19 |
zstd 1.5.7 -13 |
48,36 |
1963,91 |
34,12 |
zstd 1.5.7 -14 |
40,79 |
1975,87 |
34,03 |
zstd 1.5.7 -15 |
36,51 |
1978,59 |
34 |
zstd 1.5.7 -16 |
17,74 |
1986,73 |
33,64 |
zstd 1.5.7 -17 |
15,93 |
1962,93 |
33,6 |
zstd 1.5.7 -18 |
9,35 |
1890,08 |
33,58 |
zstd 1.5.7 -19 |
6,57 |
1900,55 |
33,46 |
zstd 1.5.7 -20 |
6,61 |
1899,66 |
33,46 |
zstd 1.5.7 -21 |
6,17 |
1908,84 |
33,45 |
zstd 1.5.7 -22 |
5,22 |
1904,06 |
33,45 |
Таблица 2. Результаты теста для CSS.
Здесь на своё место встаёт максимальное сжатие с brotli — абсолютный лидер по степени компрессии.
Для динамического режима (низкие степени) всё остаётся как и в прошлом тесте: zstd лидирует по скорости и качеству сжатия, за ним с заметным отрывом по скорости идёт brotli.
Наконец, дополним картину результатами для JS‑файла.
Compressor name/level |
Compression speed (MB/s) |
Decompression speed (MB/s) |
Ratio (%) |
zlib 1.3.1 -1 |
150,26 |
473,88 |
32,04 |
zlib 1.3.1 -2 |
137,13 |
487,89 |
30,97 |
zlib 1.3.1 -3 |
114,69 |
497,85 |
30,22 |
zlib 1.3.1 -4 |
92,34 |
496,86 |
28,47 |
zlib 1.3.1 -5 |
68,32 |
500,11 |
27,6 |
zlib 1.3.1 -6 |
51,95 |
506,68 |
27,33 |
zlib 1.3.1 -7 |
45,74 |
506,58 |
27,27 |
zlib 1.3.1 -8 |
39,88 |
506,86 |
27,24 |
zlib 1.3.1 -9 |
40,39 |
507,88 |
27,24 |
brotli 1.2.0 -0 |
465,1 |
526,78 |
32,54 |
brotli 1.2.0 -1 |
320,69 |
555,07 |
30,83 |
brotli 1.2.0 -2 |
180,75 |
603,52 |
27,96 |
brotli 1.2.0 -3 |
153,1 |
621,39 |
27,54 |
brotli 1.2.0 -4 |
117,07 |
691,56 |
26,74 |
brotli 1.2.0 -5 |
73,71 |
617,55 |
24,32 |
brotli 1.2.0 -6 |
65,74 |
631,61 |
24,02 |
brotli 1.2.0 -7 |
42,94 |
635,92 |
23,77 |
brotli 1.2.0 -8 |
36,36 |
639,2 |
23,66 |
brotli 1.2.0 -9 |
24,39 |
639,76 |
23,56 |
brotli 1.2.0 -10 |
2,18 |
571,98 |
21,8 |
brotli 1.2.0 -11 |
0,89 |
637,55 |
21,5 |
zstd 1.5.7 -1 |
529,33 |
1754,71 |
31,05 |
zstd 1.5.7 -2 |
415,27 |
1638,89 |
28,88 |
zstd 1.5.7 -3 |
321,1 |
1591 |
27,31 |
zstd 1.5.7 -4 |
307,08 |
1569,23 |
27,14 |
zstd 1.5.7 -5 |
167,69 |
1533,69 |
25,92 |
zstd 1.5.7 -6 |
122,4 |
1635,1 |
24,99 |
zstd 1.5.7 -7 |
112,82 |
1639,57 |
24,73 |
zstd 1.5.7 -8 |
89,8 |
1680,71 |
24,49 |
zstd 1.5.7 -9 |
86,47 |
1679,89 |
24,46 |
zstd 1.5.7 -10 |
67,44 |
1701,65 |
24,31 |
zstd 1.5.7 -11 |
51,91 |
1715,62 |
24,24 |
zstd 1.5.7 -12 |
51,44 |
1717,03 |
24,24 |
zstd 1.5.7 -13 |
25,31 |
1715,25 |
24,04 |
zstd 1.5.7 -14 |
21,99 |
1722,63 |
23,97 |
zstd 1.5.7 -15 |
21,2 |
1726,37 |
23,95 |
zstd 1.5.7 -16 |
11,09 |
1667,97 |
23,19 |
zstd 1.5.7 -17 |
10 |
1599,69 |
22,87 |
zstd 1.5.7 -18 |
6,5 |
1510,99 |
22,66 |
zstd 1.5.7 -19 |
5,35 |
1519,35 |
22,63 |
zstd 1.5.7 -20 |
5,3 |
1520,88 |
22,63 |
zstd 1.5.7 -21 |
5,21 |
1522,02 |
22,63 |
zstd 1.5.7 -22 |
5,13 |
1528,74 |
22,63 |
Таблица 3. Результаты теста для JS.
Результаты теста с JS‑файлом подтверждают все выводы теста с CSS, расстановка вариантов сжатия не меняется.
Из приведённых данных можно сделать нужные выводы для использования тех или иных вариантов компрессии в статическом режиме, без ограничения процессорных ресурсов. Также не стоит забывать о старых клиентах, которые поддерживают только gzip/deflate. Наибольшую степень компрессии для gzip можно получить при использовании zopfli или утилиты zstd ‑format=gzip. Подробнее эти вопросы разобраны ранее в статье про текстовое сжатие.
Но как выбрать оптимальную степень компрессии для реального применения в работе веб‑сервера? Для этого потребуется учесть несколько дополнительных факторов.
Выбор оптимальной степени динамической компрессии
Предварительно на основе результатов тестов мы определили лидера в динамической компрессии — zstd. Однако не ясно, какую степень разумно использовать для этого кодека?
С точки зрения минимизации использования процессорных ресурсов нужно использовать минимальные настройки для каждого компрессора. При этом мы получим неплохой коэффициент сжатия (около 3-х раз) и максимальную скорость компрессии.
Другой подход заключается в выборе компромиссного варианта между нагрузкой на процессор и размером передаваемого ресурса. Здесь мы уже не получим простого ответа, необходимы расчёты. Целевым параметром для оптимизации здесь может стать общее время обработки запроса, включая сжатие, декомпрессию и передачу по сети.
Представим модель процесса передачи ресурса с динамическим сжатием в виде следующих компонент, выраженных во времени:
отправка запроса (RTT);
сжатие ресурса (C);
отправка сжатого ответа(T);
декомпрессия ответа (D).
Очевидно, что для получения результирующего времени нужно ввести несколько переменных: размер файла (S), задержка в сети (RTT), и пропускная способность канала (BW). Из результатов теста нам известна скорость компрессии (Cs), декомпрессии (Ds) и коэффициент сжатия (R). Из этого можно составить формулу расчёта для полного времени обработки запроса:
Эта формула учитывает издержки на компрессию и декомпрессию ресурса, а также на передачу его по сети при заданных параметрах файла и сетевого канала.
Чтобы применить эту модель в рамках нашего теста возьмём следующие значения:
RTT 10 мс;
BW: 1 МБ/с;
S: 1 МБ.
В файле с результатами параметры задаются на листе «Settings». Эти параметры эквиваленты передаче среднего комплекта JS‑кода для сайта по достаточно скоростному мобильному подключению (около 8 Мбит/с или 10 мс задержка). Добавим расчёт этого времени для каждого варианта сжатия в таблицы с результатами (колонка «Total time»).
Если отбросить варианты со скоростью компрессии менее 50 МБ/с (как слишком медленные), то получим следующее распределение (тест CSS):

То же самое в табличной форме:
Compressor name/level |
Compression speed (MB/s) |
Ratio (%) |
Total time (ms) |
zlib 1.3.1 -1 |
101,35 |
39,58 |
416,45 |
zlib 1.3.1 -2 |
97,59 |
38,84 |
409,40 |
zlib 1.3.1 -3 |
91,37 |
38,33 |
404,97 |
zlib 1.3.1 -4 |
75,97 |
36,61 |
389,88 |
zlib 1.3.1 -5 |
67,64 |
35,97 |
385,08 |
zlib 1.3.1 -6 |
56,54 |
35,74 |
385,67 |
zlib 1.3.1 -7 |
51,55 |
35,68 |
386,79 |
brotli 1.2.0 -0 |
648,31 |
39,11 |
403,21 |
brotli 1.2.0 -1 |
511,76 |
37,66 |
389,08 |
brotli 1.2.0 -2 |
295,42 |
36,57 |
379,58 |
brotli 1.2.0 -3 |
257,88 |
36,02 |
374,55 |
brotli 1.2.0 -4 |
192,31 |
35,47 |
370,34 |
brotli 1.2.0 -5 |
130,44 |
34,67 |
364,79 |
brotli 1.2.0 -6 |
115,28 |
34,43 |
363,39 |
brotli 1.2.0 -7 |
95,35 |
34,24 |
363,30 |
brotli 1.2.0 -8 |
78,68 |
34,12 |
364,32 |
zstd 1.5.7 -1 |
832,85 |
38,31 |
394,52 |
zstd 1.5.7 -2 |
739,07 |
37,46 |
386,18 |
zstd 1.5.7 -3 |
632,15 |
36,29 |
374,70 |
zstd 1.5.7 -4 |
610,81 |
36,28 |
374,65 |
zstd 1.5.7 -5 |
292,53 |
35,13 |
364,91 |
zstd 1.5.7 -6 |
226,18 |
34,73 |
361,91 |
zstd 1.5.7 -7 |
204,83 |
34,53 |
360,36 |
zstd 1.5.7 -8 |
166,53 |
34,43 |
360,48 |
zstd 1.5.7 -9 |
161,21 |
34,42 |
360,58 |
zstd 1.5.7 -10 |
136,01 |
34,29 |
360,43 |
zstd 1.5.7 -11 |
96,99 |
34,19 |
362,38 |
zstd 1.5.7 -12 |
99,46 |
34,19 |
362,13 |
Таблица 4. Общее время для CSS.
Оптимальными с точки зрения общего времени обработки будут средние степени компрессии brotli (5-7) или zstd (7-9), при этом zstd немного обгоняет brotli. Основной вклад при наших условиях в общее время вносит компонента передачи файла, поэтому мы наблюдаем такую расстановку. Посмотрим на эти же расчёты для JS-файла:

И в табличном виде:
Compressor name/level |
Compression speed (MB/s) |
Ratio (%) |
Total time (ms) |
zlib 1.3.1 -1 |
150,26 |
32,04 |
337,73 |
zlib 1.3.1 -2 |
137,13 |
30,97 |
327,63 |
zlib 1.3.1 -3 |
114,69 |
30,22 |
321,53 |
zlib 1.3.1 -4 |
92,34 |
28,47 |
306,10 |
zlib 1.3.1 -5 |
68,32 |
27,6 |
301,19 |
zlib 1.3.1 -6 |
51,95 |
27,33 |
303,09 |
zlib 1.3.1 -7 |
45,74 |
27,27 |
305,10 |
brotli 1.2.0 -0 |
465,1 |
32,54 |
338,17 |
brotli 1.2.0 -1 |
320,69 |
30,83 |
321,97 |
brotli 1.2.0 -2 |
180,75 |
27,96 |
295,60 |
brotli 1.2.0 -3 |
153,1 |
27,54 |
292,37 |
brotli 1.2.0 -4 |
117,07 |
26,74 |
286,33 |
brotli 1.2.0 -5 |
73,71 |
24,32 |
267,16 |
brotli 1.2.0 -6 |
65,74 |
24,02 |
265,79 |
zstd 1.5.7 -1 |
529,33 |
31,05 |
322,57 |
zstd 1.5.7 -2 |
415,27 |
28,88 |
301,38 |
zstd 1.5.7 -3 |
321,1 |
27,31 |
286,39 |
zstd 1.5.7 -4 |
307,08 |
27,14 |
284,83 |
zstd 1.5.7 -5 |
167,69 |
25,92 |
275,33 |
zstd 1.5.7 -6 |
122,4 |
24,99 |
268,22 |
zstd 1.5.7 -7 |
112,82 |
24,73 |
266,31 |
zstd 1.5.7 -8 |
89,8 |
24,49 |
266,18 |
zstd 1.5.7 -9 |
86,47 |
24,46 |
266,31 |
zstd 1.5.7 -10 |
67,44 |
24,31 |
268,07 |
zstd 1.5.7 -11 |
51,91 |
24,24 |
271,81 |
zstd 1.5.7 -12 |
51,44 |
24,24 |
271,98 |
Таблица 5. Общее время для JS.
Общее распределение похоже на пример с CSS, но в лидеры за счет малого размера файла выбивается brotli 5–6. С небольшим отставанием следует zstd 7–8. Конечно, нужно учитывать, что тестирование проводилось на процессоре с высокой однопоточной производительностью.
При изменении параметров (например, повышении пропускной способности канала) расстановка будет меняться, так как вклад времени передачи будет меньше и время компрессии/декомпрессии будет иметь больший вес. Изменять параметры можно в электронной таблице из репозитория.
Для примера разберём ситуацию с низкой (примерно в 2 раза ниже) скоростью процессора (Intel Core i5-8300H на частоте около 2.0 Ghz) и высокой скоростью канала (12 МБ/c, около 100 Мбит/с), размер ресурса оставим 1 МБ. Результаты показаны на картинке ниже.

Для файла CSS получаем оптимальные настройки по общему времени передачи для zstd 3–4, для brotli оптимальный вариант 0–1. Дальнейшее увеличение скорости канала или снижение скорости процессора будет смещать настройки в сторону низких степеней компрессии еще больше.
Настало время подвести итоги статьи.
Итоги
По результатам проведённых тестов можно констатировать разгромное поражение gzip‑сжатия (zlib в тесте). Единственным преимуществом этого формата сжатия можно назвать совместимость: как со стороны клиентов, так веб‑серверов. В остальном brotli находится в жестком соревновании с zstd. В зависимости от набора данных вперёд выходит один из них. Для статического сжатия в большинстве случаев лучше подойдёт brotli 11.
Ситуация с выбором параметров динамического сжатия сложнее: оптимальный выбор зависит от пропускной способности канала и размеров ресурсов. Наиболее совместимая рекомендация: использовать средне‑низкие настройки сжатия с brotli и/или zstd (3–5). При наличии свободных процессорных ресурсов на сервере степени можно увеличить не несколько позиций.