Когда мы вчера писал о умных часах Bangle.js 2 JavaScript, мы заметили, что они использовали «сжатие с термоусадкой» в прошивке ESPruino. Мы не помним, чтобы когда-либо ранее читали о Heatshrink, и действительно, поиск в CNX Software не дал результатов.
Heatshrink — это библиотека для сжатия данных с открытым исходным кодом, разработанная для встраиваемых систем с ограниченными ресурсами, которая работает всего с 50 байтами ОЗУ. Это впечатляет, так что давайте рассмотрим.
Библиотека написана на языке C и была выпущена около 8 лет назад на Github со следующими ключевыми функциями:
- Низкое использование памяти — требуется всего 50 байт с определенными параметрами, обычно менее 300 байт.
- Инкрементное ограниченное использование ЦП — входные данные обрабатываются крошечными частями
- Статическое или динамическое распределение памяти
- Выпущено по лицензии ISC, которая позволяет вам свободно использовать библиотеку даже в коммерческих продуктах.
Внутренняя работа библиотеки объясняется следующим образом:
Термоусадка основана на LZSS , так как она особенно подходит для сжатия в небольших объемах памяти. Он может использовать необязательный небольшой индекс, чтобы значительно ускорить сжатие, но в противном случае может работать в менее 100 байтах памяти. В настоящее время индекс добавляет 2^(размер window + 1) байтов к использованию памяти для сжатия и временно выделяет 512 байтов в стеке во время построения индекса (если индекс включен).
Итак, давайте попробуем это на нашем ноутбуке, который, как мы считаем, не совсем встраиваемая система с ограниченными ресурсами.
git clone https://github.com/atomicobject/heatshrink
cd heatshrink/
make
После завершения сборки мы получим библиотеки (libheatshrink_dynamic.a
и libheatshrink_static.a), которые вы можете использовать для интеграции в свой собственный проект, а также один двоичный файл размером 109 КБ (27 КБ после удаления), называемый heatshrink для кодирования и декодирования файлов. Обратите внимание, что при компиляции для микроконтроллера Arduino с avr-gcc декодером занимает всего около 1 КБ дискового пространства.
Но прежде чем использовать утилиты, мы должны разобраться в трех вариантах:
- window_sz2, -w — устанавливает размер window 2^W байт. Размер окна определяет, насколько далеко во входных данных можно искать повторяющиеся шаблоны. Window_sz2 из 8 будет использовать только 256 байтов (2^8), в то время как window_sz2 из 10 будет использовать 1024 байта (2^10) с компромиссами с точки зрения использования памяти и степени сжатия. Его можно установить от 4 до 15.
- lookahead_sz2, -l — устанавливает размер lookahead равным 2^L байт. Размер lookahead определяет максимальную длину для найденных повторяющихся шаблонов. Например, если lookahead_sz2 равен 4, 50-байтовый запуск символов «a» будет представлен как несколько повторяющихся 16-байтовых шаблонов (2^4 равно 16). Обычно он равен примерно половине размера windows_sz2.
Позвольте сжать/закодировать последний список изменений Linux 5.14 с тепловым сжатием, используя параметры 8/4 и 13/4:
time ./heatshrink -e -w 8 -l 4 Linux-5.14-Changelog.txt Linux-5.14-Changelog.txt.hs
real 0m1.346s
user 0m1.323s
sys 0m0.016s
time ./heatshrink -e -w 13 -l 4 Linux-5.14-Changelog.txt Linux-5.14-Changelog.txt.hs2
real 0m4.689s
user 0m4.659s
sys 0m0.008s
Это займет больше времени и потребляет больше памяти и циклов ЦП с большим размером окна, но степень сжатия также намного лучше.
ls -l Linux-5.14-Changelog*
-rw-rw-r-- 1 jaufranc jaufranc 16282443 Sep 28 20:20 Linux-5.14-Changelog.txt
-rw-r--r-- 1 jaufranc jaufranc 10854495 Sep 28 20:22 Linux-5.14-Changelog.txt.hs
-rw-r--r-- 1 jaufranc jaufranc 6203196 Sep 28 20:27 Linux-5.14-Changelog.txt.hs2
Таким образом, вам придется настроить это, чтобы оптимизировать значения с учетом ресурсов, доступных для ваших целей. Чтобы распаковать, нам просто нужно заменить первый аргумент:
time ./heatshrink -d Linux-5.14-Changelog.txt.hs2 Linux-5.14-Changelog-decompressed.txt
real 0m0.486s
user 0m0.458s
sys 0m0.024s
Декомпрессия происходит быстрее. Быстрая проверка с помощью diff показывает, что файлы идентичны.
Makefile также поставляется с опцией тестирования (но сначала нам пришлось загрузить файл cantrbry.tar.gz вручную), который будет тестировать различные файлы и настройки:
make bench
mkdir -p benchmark_out
cd benchmark_out && tar vzxf ../cantrbry.tar.gz
alice29.txt
asyoulik.txt
cp.html
fields.c
grammar.lsp
kennedy.xls
lcet10.txt
plrabn12.txt
ptt5
sum
xargs.1
time ./benchmark
pass: -w 6 -l 5 alice29.txt
pass: -w 6 -l 5 asyoulik.txt
pass: -w 6 -l 5 cp.html
pass: -w 6 -l 5 fields.c
pass: -w 6 -l 5 grammar.lsp
pass: -w 6 -l 5 kennedy.xls
pass: -w 6 -l 5 lcet10.txt
pass: -w 6 -l 5 plrabn12.txt
pass: -w 6 -l 5 ptt5
pass: -w 6 -l 5 sum
pass: -w 6 -l 5 xargs.1
pass: -w 7 -l 5 alice29.txt
pass: -w 7 -l 5 asyoulik.txt
pass: -w 7 -l 5 cp.html
pass: -w 7 -l 5 fields.c
pass: -w 7 -l 5 grammar.lsp
pass: -w 7 -l 5 kennedy.xls
pass: -w 7 -l 5 lcet10.txt
pass: -w 7 -l 5 plrabn12.txt
pass: -w 7 -l 5 ptt5
pass: -w 7 -l 5 sum
pass: -w 7 -l 5 xargs.1
pass: -w 7 -l 6 alice29.txt
pass: -w 7 -l 6 asyoulik.txt
pass: -w 7 -l 6 cp.html
pass: -w 7 -l 6 fields.c
pass: -w 7 -l 6 grammar.lsp
pass: -w 7 -l 6 kennedy.xls
pass: -w 7 -l 6 lcet10.txt
pass: -w 7 -l 6 plrabn12.txt
pass: -w 7 -l 6 ptt5
pass: -w 7 -l 6 sum
pass: -w 7 -l 6 xargs.1
pass: -w 8 -l 5 alice29.txt
pass: -w 8 -l 5 asyoulik.txt
pass: -w 8 -l 5 cp.html
pass: -w 8 -l 5 fields.c
pass: -w 8 -l 5 grammar.lsp
pass: -w 8 -l 5 kennedy.xls
pass: -w 8 -l 5 lcet10.txt
pass: -w 8 -l 5 plrabn12.txt
pass: -w 8 -l 5 ptt5
pass: -w 8 -l 5 sum
pass: -w 8 -l 5 xargs.1
pass: -w 8 -l 6 alice29.txt
pass: -w 8 -l 6 asyoulik.txt
pass: -w 8 -l 6 cp.html
pass: -w 8 -l 6 fields.c
pass: -w 8 -l 6 grammar.lsp
pass: -w 8 -l 6 kennedy.xls
pass: -w 8 -l 6 lcet10.txt
pass: -w 8 -l 6 plrabn12.txt
pass: -w 8 -l 6 ptt5
pass: -w 8 -l 6 sum
pass: -w 8 -l 6 xargs.1
pass: -w 8 -l 7 alice29.txt
pass: -w 8 -l 7 asyoulik.txt
pass: -w 8 -l 7 cp.html
pass: -w 8 -l 7 fields.c
pass: -w 8 -l 7 grammar.lsp
pass: -w 8 -l 7 kennedy.xls
pass: -w 8 -l 7 lcet10.txt
pass: -w 8 -l 7 plrabn12.txt
pass: -w 8 -l 7 ptt5
pass: -w 8 -l 7 sum
pass: -w 8 -l 7 xargs.1
pass: -w 9 -l 5 alice29.txt
pass: -w 9 -l 5 asyoulik.txt
pass: -w 9 -l 5 cp.html
pass: -w 9 -l 5 fields.c
pass: -w 9 -l 5 grammar.lsp
pass: -w 9 -l 5 kennedy.xls
pass: -w 9 -l 5 lcet10.txt
pass: -w 9 -l 5 plrabn12.txt
pass: -w 9 -l 5 ptt5
pass: -w 9 -l 5 sum
pass: -w 9 -l 5 xargs.1
pass: -w 9 -l 6 alice29.txt
pass: -w 9 -l 6 asyoulik.txt
pass: -w 9 -l 6 cp.html
pass: -w 9 -l 6 fields.c
pass: -w 9 -l 6 grammar.lsp
pass: -w 9 -l 6 kennedy.xls
pass: -w 9 -l 6 lcet10.txt
pass: -w 9 -l 6 plrabn12.txt
pass: -w 9 -l 6 ptt5
pass: -w 9 -l 6 sum
pass: -w 9 -l 6 xargs.1
pass: -w 9 -l 7 alice29.txt
pass: -w 9 -l 7 asyoulik.txt
pass: -w 9 -l 7 cp.html
pass: -w 9 -l 7 fields.c
pass: -w 9 -l 7 grammar.lsp
pass: -w 9 -l 7 kennedy.xls
pass: -w 9 -l 7 lcet10.txt
pass: -w 9 -l 7 plrabn12.txt
pass: -w 9 -l 7 ptt5
pass: -w 9 -l 7 sum
pass: -w 9 -l 7 xargs.1
pass: -w 9 -l 8 alice29.txt
pass: -w 9 -l 8 asyoulik.txt
pass: -w 9 -l 8 cp.html
pass: -w 9 -l 8 fields.c
pass: -w 9 -l 8 grammar.lsp
pass: -w 9 -l 8 kennedy.xls
pass: -w 9 -l 8 lcet10.txt
pass: -w 9 -l 8 plrabn12.txt
pass: -w 9 -l 8 ptt5
pass: -w 9 -l 8 sum
pass: -w 9 -l 8 xargs.1
pass: -w 10 -l 5 alice29.txt
pass: -w 10 -l 5 asyoulik.txt
pass: -w 10 -l 5 cp.html
pass: -w 10 -l 5 fields.c
pass: -w 10 -l 5 grammar.lsp
pass: -w 10 -l 5 kennedy.xls
pass: -w 10 -l 5 lcet10.txt
pass: -w 10 -l 5 plrabn12.txt
pass: -w 10 -l 5 ptt5
pass: -w 10 -l 5 sum
pass: -w 10 -l 5 xargs.1
pass: -w 10 -l 6 alice29.txt
pass: -w 10 -l 6 asyoulik.txt
pass: -w 10 -l 6 cp.html
pass: -w 10 -l 6 fields.c
pass: -w 10 -l 6 grammar.lsp
pass: -w 10 -l 6 kennedy.xls
pass: -w 10 -l 6 lcet10.txt
pass: -w 10 -l 6 plrabn12.txt
pass: -w 10 -l 6 ptt5
pass: -w 10 -l 6 sum
pass: -w 10 -l 6 xargs.1
pass: -w 10 -l 7 alice29.txt
pass: -w 10 -l 7 asyoulik.txt
pass: -w 10 -l 7 cp.html
pass: -w 10 -l 7 fields.c
pass: -w 10 -l 7 grammar.lsp
pass: -w 10 -l 7 kennedy.xls
pass: -w 10 -l 7 lcet10.txt
pass: -w 10 -l 7 plrabn12.txt
pass: -w 10 -l 7 ptt5
pass: -w 10 -l 7 sum
pass: -w 10 -l 7 xargs.1
pass: -w 10 -l 8 alice29.txt
pass: -w 10 -l 8 asyoulik.txt
pass: -w 10 -l 8 cp.html
pass: -w 10 -l 8 fields.c
pass: -w 10 -l 8 grammar.lsp
pass: -w 10 -l 8 kennedy.xls
pass: -w 10 -l 8 lcet10.txt
pass: -w 10 -l 8 plrabn12.txt
pass: -w 10 -l 8 ptt5
pass: -w 10 -l 8 sum
pass: -w 10 -l 8 xargs.1
pass: -w 11 -l 5 alice29.txt
pass: -w 11 -l 5 asyoulik.txt
pass: -w 11 -l 5 cp.html
pass: -w 11 -l 5 fields.c
pass: -w 11 -l 5 grammar.lsp
pass: -w 11 -l 5 kennedy.xls
pass: -w 11 -l 5 lcet10.txt
pass: -w 11 -l 5 plrabn12.txt
pass: -w 11 -l 5 ptt5
pass: -w 11 -l 5 sum
pass: -w 11 -l 5 xargs.1
pass: -w 11 -l 6 alice29.txt
pass: -w 11 -l 6 asyoulik.txt
pass: -w 11 -l 6 cp.html
pass: -w 11 -l 6 fields.c
pass: -w 11 -l 6 grammar.lsp
pass: -w 11 -l 6 kennedy.xls
pass: -w 11 -l 6 lcet10.txt
pass: -w 11 -l 6 plrabn12.txt
pass: -w 11 -l 6 ptt5
pass: -w 11 -l 6 sum
pass: -w 11 -l 6 xargs.1
pass: -w 11 -l 7 alice29.txt
pass: -w 11 -l 7 asyoulik.txt
pass: -w 11 -l 7 cp.html
pass: -w 11 -l 7 fields.c
pass: -w 11 -l 7 grammar.lsp
pass: -w 11 -l 7 kennedy.xls
pass: -w 11 -l 7 lcet10.txt
pass: -w 11 -l 7 plrabn12.txt
pass: -w 11 -l 7 ptt5
pass: -w 11 -l 7 sum
pass: -w 11 -l 7 xargs.1
pass: -w 11 -l 8 alice29.txt
pass: -w 11 -l 8 asyoulik.txt
pass: -w 11 -l 8 cp.html
pass: -w 11 -l 8 fields.c
pass: -w 11 -l 8 grammar.lsp
pass: -w 11 -l 8 kennedy.xls
pass: -w 11 -l 8 lcet10.txt
pass: -w 11 -l 8 plrabn12.txt
pass: -w 11 -l 8 ptt5
pass: -w 11 -l 8 sum
pass: -w 11 -l 8 xargs.1
pass: -w 12 -l 5 alice29.txt
pass: -w 12 -l 5 asyoulik.txt
pass: -w 12 -l 5 cp.html
pass: -w 12 -l 5 fields.c
pass: -w 12 -l 5 grammar.lsp
pass: -w 12 -l 5 kennedy.xls
pass: -w 12 -l 5 lcet10.txt
pass: -w 12 -l 5 plrabn12.txt
pass: -w 12 -l 5 ptt5
pass: -w 12 -l 5 sum
pass: -w 12 -l 5 xargs.1
pass: -w 12 -l 6 alice29.txt
pass: -w 12 -l 6 asyoulik.txt
pass: -w 12 -l 6 cp.html
pass: -w 12 -l 6 fields.c
pass: -w 12 -l 6 grammar.lsp
pass: -w 12 -l 6 kennedy.xls
pass: -w 12 -l 6 lcet10.txt
pass: -w 12 -l 6 plrabn12.txt
pass: -w 12 -l 6 ptt5
pass: -w 12 -l 6 sum
pass: -w 12 -l 6 xargs.1
pass: -w 12 -l 7 alice29.txt
pass: -w 12 -l 7 asyoulik.txt
pass: -w 12 -l 7 cp.html
pass: -w 12 -l 7 fields.c
pass: -w 12 -l 7 grammar.lsp
pass: -w 12 -l 7 kennedy.xls
pass: -w 12 -l 7 lcet10.txt
pass: -w 12 -l 7 plrabn12.txt
pass: -w 12 -l 7 ptt5
pass: -w 12 -l 7 sum
pass: -w 12 -l 7 xargs.1
pass: -w 12 -l 8 alice29.txt
pass: -w 12 -l 8 asyoulik.txt
pass: -w 12 -l 8 cp.html
pass: -w 12 -l 8 fields.c
pass: -w 12 -l 8 grammar.lsp
pass: -w 12 -l 8 kennedy.xls
pass: -w 12 -l 8 lcet10.txt
pass: -w 12 -l 8 plrabn12.txt
pass: -w 12 -l 8 ptt5
pass: -w 12 -l 8 sum
pass: -w 12 -l 8 xargs.1
====
Total compression: 11541.96% for 242 documents (avg. 47.69%)
14.40user 1.59system 0:15.07elapsed 106%CPU (0avgtext+0avgdata 4392maxresident)k
120inputs+175640outputs (21major+266723minor)pagefaults 0swaps
Было бы неплохо сравнить heatshrink с другой популярной библиотекой для сжатия данных, такой как gzip, и это именно то, что Скотт Вокес озвучил в своем блоге после того, как выпустил библиотеку в 2013 году.
gzip имеет лучшую степень сжатия, но, очевидно, использует намного больше ОЗУ, чем тепловое сжатие, и с использованием более 128 КБ ОЗУ не подходит для многих микроконтроллеров. Если вы используете библиотеку сжатия с более низкими настройками, вы можете проверить, действительно ли она не увеличивает размер, поскольку параметры HS 6,3 и HS 5,3 в приведенной выше таблице имели некоторые из сжатых файлов большего размера, чем оригинал. Тем не менее, это хороший вариант, и мы видим, что кто-то сделал библиотеку Arduino на основе Heatshrink.
Выражаем свою благодарность источнику из которого взята и переведена статья, сайту cnx-software.com.
Оригинал статьи вы можете прочитать здесь.