Я пытался понять алгоритм gzip в контексте потоковых HTTP-соединений (SSE и различные кометные технологии). Я протестировал несколько альтернативных представлений данных с такими размерами файлов:
40 csv.txt
63 json-short.txt
80 json-readable.txt
27 rawbin.txt
46 sse.csv.txt
69 sse.json-short.txt
86 sse.json-readable.txt
При сжатии с помощью gzip -9v
я получаю:
csv.txt: 25.0%
json-readable.txt: 16.2%
json-short.txt: 20.6%
rawbin.txt: 18.5%
sse.csv.txt: 25.0%
sse.json-readable.txt: 15.1%
sse.json-short.txt: 18.8%
Это не очень хорошие коэффициенты сжатия, но они оказались обратными ожиданиям: более подробные форматы JSON сжимаются хуже.
Мой вопрос: улучшается ли сжатие по мере потоковой передачи все большего количества данных? Узнает ли он динамически и неявно, какие биты являются каркасными, а какие — переменными данными? Если это алгоритм обучения, есть ли момент, когда он прекращает обучение, или он теоретически всегда адаптируется к потоку данных? И если да, то придается ли дополнительный вес более свежим данным?
Я провел грубый тест, объединив cat
25 файлов sse.json-readable.txt в один файл. Затем Gzip дал мне степень сжатия 95,7%. Но я описываю это как грубое по двум причинам. Сначала каждая строка данных была идентична, тогда как в реальных данных числа и временные метки будут немного отличаться, и только структура будет одинаковой. Вторая причина заключается в том, что gzip дается один файл: выполняет ли алгоритм gzip предварительное сканирование данных, чтобы изучить их, или прыгает по файлу? Если это так, эти результаты не будут применяться к потоковым данным Apache (поскольку он уже сжал и отправил первую строку данных до того, как увидит вторую строку).
В качестве второстепенного вопроса могу ли я предположить, что время не является фактором? Например. предполагая, что переподключение сокета не задействовано, между каждой строкой данных может быть 1-секундный интервал или 60-секундный интервал.
Полезная ссылка о том, как работает gzip: http://www.infinitepartitions.com/art001.html
(Кстати, мое текущее понимание состоит в том, что сжатие при потоковой передаче будет основано исключительно на анализе первого блока данных, поэтому мне интересно, смогу ли я улучшить сжатие, отправив несколько строк фиктивных данных, чтобы дать это шанс научиться лучшему сжатию?!?)
http://svn.apache.org/repos/asf/httpd/httpd/trunk/modules/filters/mod_deflate.c 15 — это то, что дает 32 КБ.
http://www.zlib.net/zlib_how.html http://www.zlib.net/zlib_tech.html
ОБНОВЛЕНИЕ: ПОЛЕЗНЫЕ ССЫЛКИ
Вот код модуля Apache: http://svn.apache.org/repos/asf/httpd/httpd/trunk/modules/filters/mod_deflate.c
Размер окна 15 - это то, что дает окно размером 32 КБ, о котором Марк Адлер упоминает в своем ответе.
Вот несколько страниц, которые помогут понять код Apache: http://www.zlib.net/zlib_how.html http://www.zlib.net/zlib_tech.html
Вот приведенные выше тестовые файлы, если вам интересно:
csv.txt
2013-03-29 03:15:24,EUR/USD,1.303,1.304
json-short.txt
{"t":"2013-03-29 06:09:03","s":"EUR\/USD","b":1.303,"a":1.304}
json-readable.txt
{"timestamp":"2013-03-29 06:09:03","symbol":"EUR\/USD","bid":1.303,"ask":1.304}
sse.csv.txt
data:2013-03-29 03:15:24,EUR/USD,1.303,1.304
sse.json-short.txt
data:{"t":"2013-03-29 06:09:03","s":"EUR\/USD","b":1.303,"a":1.304}
sse.json-readable.txt
data:{"timestamp":"2013-03-29 06:09:03","symbol":"EUR\/USD","bid":1.303,"ask":1.304}
ПРИМЕЧАНИЕ: версии sse.* заканчиваются двумя LF, остальные - одним LF.
rawbin.txt был создан с помощью этого PHP-скрипта:
$s=pack("la7dd",time(),"USD/JPY",1.303,1.304);
file_put_contents("rawbin.txt",$s);