Веб-разработка / Про XML, base64, Android, HTTPS и сжатие

в 14:24, , рубрики: android, base64, HTTPS, XML, сжатие, метки: , , , ,

Веб-разработка / Про XML, base64, Android, HTTPS и сжатие
Прогресс неумолимо движется вперед! Развитие Web, повышение сложности приложений, использование таких стандартов, как HTML, CSS, XML, JSON и т.д. требует все больше и больше ресурсов. С одной стороны это оправдано, т.к. приоритетом здесь является функциональность. С другой стороны, повышение требований к вычислительным и сетевым ресурсам не может остаться без контроля, иначе они перекроют доступные ресурсы производителей оборудования.
Одним из ресурсов, за которым требуется следить, является размер данных: документов, файлов, баз данных. Современная страничка на www.yandex.ru требует загрузки данных общим размером почти 200 килобайт и всего 20 лет назад загружалась бы три минуты на модеме со скоростью 9600 (без использования MNP5 и V.42bis).
Недостаточная скорость роста доступных ресурсов компенсируется процессом их экономии. Так, сжатие данных (преобразование производимое с целью уменьшения объёма данных) — одна из широко используемых техник оптимизации, когда дорого обходится занимаемая память или процесс передачи данных.
И в Web, и в мобильных приложениях, где нехватка ресурсов, в т.ч. доступного объема для хранения данных, широко применяется сжатие. О некоторых моментах применение сжатия и пойдет речь в данной статье.
Как работает сжатие

В двух словах, алгоритмы сжатия работают на основе статистической неравномерности и повторении данных. В частности, это относится к алгоритму сжатия DEFLATE, который использует комбинацию алгоритма LZ77 и алгоритма Хаффмана.
Теория нам говорит, что если символы в тексте встречаются с разной частотой, то этот текст можно сжать. После сжатия частота символов обязательно выравнивается, поэтому когда-то сжатый файл снова сжать гораздо труднее или вообще невозможно, хотя есть интересное исключение из этого правила, о котором будет рассказано ниже.
На сжатие может влияет структура сжимаемых данных, или то, как ее интерпретирует алгоритм сжатия. Для пояснения этого хочу показать эксперимент с XML-файлом и архиватором ZIP. Замечу, что и то, и другое имеет отношение к практике.
Есть некоторый XML-файл размером примерно 420 килобайт. Если его сжать архиватором ZIP, то получим архив размером 80 килобайт. Размер уменьшился в пять раз, что типичный показатель для текстовых файлов.
Теперь возьмем и получим аналоги исходного XML-файла в двух видах: в кодировке Base64 и HEX. Перевод в Base64 увеличил размер файла в 1.333, что составило 570 килобайт (т.к. на каждый байт нового файла эффективно теперь используется лишь 6 бит из 8), а перевод в HEX увеличил размер ровно в два раза (т.к. каждый байт заменился своим двухбайтовым HEX-представлением, т.е. латинское 'a' перешло в '61' и т.п.). Размер файла в HEX-представлении составил 850 килобайт.
Попытаемся сжать полученные производные файлы с помощью ZIP и сразу увидим необычную вещь. Напомню, что оба файла по сути содержат одну и ту же информацию. Хотя Base64-файл меньше HEX-файла, размер его архив получился больше! Архив Base64 файла получился размером 130 килобайт, а архив HEX-файла только 100 килобайт.
Так как алфавит для архиватора ZIP, по сути, состоит из символов, выровненных по байтам, он не смог понять структуру Base64-файла с 6-битными символами и справился со сжатием заметно хуже. В HEX-файле граница символов осталась на границе байт, поэтому ZIP со сжатием этого файла справился более менее хорошо.
Этот пример имеет практическое значение, т.к. в случае, если используются XML-файлы, которые содержат бинарные вставки и затем упаковываются (GZIP, DEFLATE и т.п.) для экономии трафика, то на самом деле выгоднее эти вставки делать не в Base64-кодировке, а в HEX, что может противоречить интуиции.
XML и Google Andoid

В системе Google Android ресурсы, представленные в виде XML-файлов компилируются в бинарный формат. Тем, кому не нравится тестовый XML из-за его многословности изначально это может понравится, однако, давайте проверим это на практике.
Возьмем все тот же XML файл, что в предыдущем примере и посмотрим за его преобразованием. Для данного файла его бинарное представление получилось около 800 килобайт, что больше размера исходного текстового представления в 420 килобайт.
Попробуем его сжать ZIP (JAR) и получим, что архив бинарного XML составляет 140 килобайт, что больше размера архива текстового XML, имеющего размер 80 килобайт.
Какой из этого можно сделать вывод? То, что применение бинарного XML здесь было сделано в первую очередь с целью экономии ресурсов процессора при его разборе, а не для уменьшения размера дистрибутивного apk-файла.
Сжатие в Web

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

Данные, передаваемые от браузера к серверу (например, передаваемые методом POST) не сжимаются (хотя в редких случаях могут и сжиматься: если есть специальный HTTP-клиент и HTTP-сервер это поймет).

Один из механизмов сжатия — повторение, не работает на уровне цепочки запросов, что уменьшает эффективность сжатия.

Признаком использования такого метода сжатия является заголовок «Content-Encoding: gzip/deflate» в ответе.
Сжатие и HTTPЫ HTTPS

Как это может быть не удивительно, но HTTPS может использоваться не только для защиты, но и для сжатия данных. Протоколы SSLv3 и TLS дают возможность договорится сторонам об использовании сжатия при установке соединения. При этом, такой способ выглядит привлекательней метода с «Content-Encoding:gzip/deflate». Во первых, сжимаются все данные (включая заголовки), идущие в обе стороны. Во вторых, при сжатии может учитываться история запросов/ответов, что повышает эффективность сжатия. Т.е. здесь отсутствуют все три недостатка предыдущего метода.
Исследуем сжатие в HTTPS

Что бы проверить, как используется ли сжатие в Web нужно иметь две вещи: знать сайт, который поддерживает такое сжатие (желательно, что бы он мог отдавать трафик и по HTTP, для сравнения), и нужно иметь инструмент.
В качестве сайта для проверки отлично подходит Wikipedia. Она равноценно позволяет обращаться к страницам как по HTTP, так и по HTTPS.
В качестве инструмента можно использовать утилиту openssl. Проверим поддержку сжатия такой командой:openssl s_client -no_ssl2 -connect wikipedia.org:443
Если в результате подключения видим строчку «Compression: 1 (zlib compression)», значит сжатие поддерживается и работает, это оно!
Compression: 1 (zlib compression)
Start Time: 1329485263
Timeout : 300 (sec)
...

По задумке разработчиков Google Chrome, в нем так же можно посмотреть наличие сжатия при использовании HTTPS, однако этот индикатор сообщает о сжатии «крайне нестабильно» и его логика работы мне не понятна. Часто он сообщает, что сжатия нет, хотя оно есть. Рабочий индикатор выглядит так, как показано на картинке:
Выше идет обращение к одной из страниц Wikipedia, при этом наблюдаются интересные эффекты. Замечу, что запрос возвращает страницу, уже сжатую GZIP (с помощью Content-Encoding, до сжатия GZIP страница имеет размер 32 килобайта, после сжатия GZIP около 9), но так как по HTTPS при сжатии используется история запросов, то уже сжатые данные могут сжаться еще раз. Периодически наблюдается «чудо природы» в виде сжатия 9 килобайт архива GZIP в 393 байта (или меньше).
Для сравнения, так выглядят запросы по HTTP:
Подводя итоги

Надеюсь, что это обзорная статья поможет разработчикам в использовании сжатия данных. И конечно же, хотелось показать практические примеры из реальной жизни по этой теме.
Спасибо за внимание.

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js