Когда мы вчера писал о умных часах Bangle.js 2 JavaScript, мы заметили, что они использовали «сжатие с термоусадкой» в прошивке ESPruino. Мы не помним, чтобы когда-либо ранее читали о Heatshrink, и действительно, поиск в CNX Software не дал результатов.
Heatshrink – это библиотека для сжатия данных с открытым исходным кодом, разработанная для встраиваемых систем с ограниченными ресурсами, которая работает всего с 50 байтами ОЗУ. Это впечатляет, так что давайте рассмотрим.
Библиотека написана на языке C и была выпущена около 8 лет назад на Github со следующими ключевыми функциями:
- Низкое использование памяти – требуется всего 50 байт с определенными параметрами, обычно менее 300 байт.
- Инкрементное ограниченное использование ЦП – входные данные обрабатываются крошечными частями
- Статическое или динамическое распределение памяти
- Выпущено по лицензии ISC, которая позволяет вам свободно использовать библиотеку даже в коммерческих продуктах.
Внутренняя работа библиотеки объясняется следующим образом:
Термоусадка основана на LZSS , так как она особенно подходит для сжатия в небольших объемах памяти. Он может использовать необязательный небольшой индекс, чтобы значительно ускорить сжатие, но в противном случае может работать в менее 100 байтах памяти. В настоящее время индекс добавляет 2^(размер window + 1) байтов к использованию памяти для сжатия и временно выделяет 512 байтов в стеке во время построения индекса (если индекс включен).
Итак, давайте попробуем это на нашем ноутбуке, который, как мы считаем, не совсем встраиваемая система с ограниченными ресурсами.
1 2 3 |
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:
1 2 3 4 5 6 7 8 9 10 11 |
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 |
Это займет больше времени и потребляет больше памяти и циклов ЦП с большим размером окна, но степень сжатия также намного лучше.
1 2 3 4 |
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 |
Таким образом, вам придется настроить это, чтобы оптимизировать значения с учетом ресурсов, доступных для ваших целей. Чтобы распаковать, нам просто нужно заменить первый аргумент:
1 2 3 4 5 |
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 вручную), который будет тестировать различные файлы и настройки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 |
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.
Оригинал статьи вы можете прочитать здесь.