Skip to content

Releases: BrianPugh/tamp

v2.3.0

Choose a tag to compare

@BrianPugh BrianPugh released this 09 Jul 19:58
32034ab

This is a correctness- and robustness-focused release. The compressed bitstream format is unchanged and remains backwards-compatible; all fixes below preserve round-trip compatibility with streams produced by earlier 2.x versions.

Bug Fixes

  • C core (extended format & init): fix a dropped run byte when a length-1 RLE run ends across poll calls (now re-emitted as a literal), invalidate the lazy-match cache after extended/RLE handling mutates the window, and reject extended streams before marking the decompressor configured so a retry can't reinterpret them as classic format. Adds a compile-time guard against a too-small stream work buffer. (#328)
  • Python bindings: validate custom dictionary sizes — the compressor requires exactly 2**window bytes, and the decompressor accepts any buffer of at least 2**window bytes, using the window-size prefix (a too-small buffer previously indexed out of bounds) — trim zero-padding from short one-shot reads, support read-only file objects in the decompressor (with an over-return guard), and stop raising on empty write(). (#329)
  • MicroPython: bounds-check window references in the viper decompressor and hoist the window-edge check out of the viper compressor match loop (fixing OOB reads), and align the native module's initialize_dictionary signature with CPython — initialize_dictionary(source, seed=None, literal=8). Note: passing literal positionally as the 2nd argument now raises; pass it as the 3rd argument or by keyword. (#330)
  • ESP32: fix out-of-bounds window reads in the SIMD/scalar match search near the window boundary and on unaligned tails. (#333)
  • WASM: flush() now defaults to write_token=true, matching the Python API, so a mid-stream flush keeps the decompressor byte-aligned. Pass flush(false) at true end-of-stream. (#332)
  • CLI: the CLI no longer crashes when built without the C extensions (dictionary building raises a clear error instead), and TAMP_SANITIZE=1 on Windows now fails with a clear message instead of a NameError. (#334)
  • Viper Compressor: require an exact dictionary size, matching the other compressors. (#335)

Optimizations

  • Embedded find_best_match: word-at-a-time (SWAR) skip over non-matching bytes — ~16% faster compression on Cortex-M0+. (#331)
  • ESP32 extended-mode search: faster longest-match search with compile-time long-verify selection. (#333)
  • ESP32 decompression: word-at-a-time window and output copies. (#336)

Other

  • ESP32 gains host-side differential and fuzz verification against the reference implementation. (#333)
  • Packaging: the Python build tooling migrated from Poetry to uv. Binary wheels no longer bundle C/Cython sources and the Linux extension is symbol-stripped, and the sdist has been pruned of dev-only files — both artifacts are significantly smaller. Installation is unchanged. (#339)
  • README benchmark and binary-size numbers refreshed to current measurements.

Full Changelog: v2.2.4...v2.3.0

v2.2.4

Choose a tag to compare

@BrianPugh BrianPugh released this 11 Jun 00:45
e5f7327

What's Changed

  • Use PyPI trusted publishing in upload_to_pypi job by @BrianPugh in #320
  • Add a double-FLUSH guard to prevent dictionary-reset desync by @BrianPugh in #319

Full Changelog: v2.2.3...v2.2.4

v2.2.3

Choose a tag to compare

@BrianPugh BrianPugh released this 30 May 18:09

What's Changed

Full Changelog: v2.2.2...v2.2.3

v2.2.2

Choose a tag to compare

@BrianPugh BrianPugh released this 04 May 16:53

Bug Fixes

Full Changelog: v2.2.1...v2.2.2

v2.2.1

Choose a tag to compare

@BrianPugh BrianPugh released this 23 Apr 14:09
3c78db6

ESP32-centric release.

Bug Fixes

Full Changelog: v2.2.0...v2.2.1

v2.2.0

Choose a tag to compare

@BrianPugh BrianPugh released this 07 Apr 01:19
9577a88

Features

Add the build-dictionary command to the CLI that builds a custom dictionary from a given corpus. Used to improve compression on similar, short messages.

No changes to compressor/decompressor code in this release.

Full Changelog: v2.1.0...v2.2.0

v2.1.0

Choose a tag to compare

@BrianPugh BrianPugh released this 27 Mar 01:14
33b79dd

Motivation

Add capabilities that allows for easy appending to a compressed stream (e.g. file) without having to reconstruct the compressor's state.

Summary

  • Add dictionary reset via double-FLUSH token sequence, enabling append-to-stream without retaining prior compressor state. Both sides re-initialize the window and continue with a fresh dictionary.
  • Uses the previously reserved more_header header bit to signal dictionary-reset-capable streams (as well as an additional header byte to follow, currently 0x00). Old decompressors (<2.1.0) reject these streams at the header, preventing silent corruption.
  • Add conf.append mode: writes a FLUSH instead of a header, allowing a new compressor to resume an existing stream.

Protocol

  • more_header (header byte 1, bit 0) now additionally signals dictionary_reset
  • Header byte 2 added (all bits reserved, must be zero)
  • Two consecutive FLUSH tokens signal dictionary re-initialization
  • FLUSH is always emitted (even when byte-aligned) in more_header streams to support append detection

API

  • TampConf.dictionary_reset / TampConf.append config fields
  • tamp_compressor_reset_dictionary() (C) / Compressor.reset_dictionary() (Python/JS)
  • Decompressor automatically handles double-FLUSH when more_header is set

Full Changelog: v2.0.0...v2.1.0

v2.0.0

Choose a tag to compare

@BrianPugh BrianPugh released this 05 Mar 02:42
79ab300

Summary

Tamp v2 adds two new compression token types via the extended header flag (enabled by default):

  • RLE: Run-length encoding for repeated bytes (up to 241 per token)
  • Extended Match: Longer pattern matches beyond v1's min_pattern_size + 13 limit (up to min_pattern_size + 131)

Compression improvements range from 0.2% to 21% depending on dataset, with binary/structured data benefiting most.

Breaking Changes

  • The enhanced format (extended=True) cannot be decompressed by tamp <2.0.0. Use extended=False for backwards compatibility.
    • Header bit [1]: Previously reserved (always 0), now indicates extended format. Old decompressors reject v2 streams safely.
  • Callback semantics: tamp_callback_t now consistently reports input bytes consumed (was inconsistent in v1).
    • Previously it was inconsistent between APIs.
  • CLI: Now an optional extra (pip install tamp[cli]). This allows for the normal tamp package to be installed without all the CLI dependencies (for use as a normal python library).
  • Dictionary initialization: tamp_initialize_dictionary takes a new literal parameter; per-literal seed tables for literal=5,6.

Migration Guide

See Migrating to v2 for full details.

Compression Results

dataset raw Baseline +lazy +extended +lazy +extended
enwik8 100,000,000 51,635,633 51,252,694 (−0.7%) 51,016,917 (−1.2%) 50,625,930 (−2.0%)
RPI_PICO (.uf2) 667,648 331,310 329,893 (−0.4%) 289,454 (−12.6%) 290,577 (−12.3%)
silesia/dickens 10,192,446 5,546,761 5,511,681 (−0.6%) 5,538,353 (−0.2%) 5,502,834 (−0.8%)
silesia/mozilla 51,220,480 25,121,385 24,937,036 (−0.7%) 24,413,362 (−2.8%) 24,229,925 (−3.5%)
silesia/mr 9,970,564 5,027,032 4,888,930 (−2.7%) 4,520,091 (−10.1%) 4,391,864 (−12.6%)
silesia/nci 33,553,445 8,643,610 8,645,399 (+0.0%) 6,824,403 (−21.0%) 6,772,307 (−21.6%)
silesia/ooffice 6,152,192 3,814,938 3,798,393 (−0.4%) 3,773,003 (−1.1%) 3,755,046 (−1.6%)
silesia/osdb 10,085,684 8,520,835 8,518,502 (−0.0%) 8,466,875 (−0.6%) 8,464,328 (−0.7%)
silesia/reymont 6,627,202 2,847,981 2,820,948 (−0.9%) 2,818,554 (−1.0%) 2,788,774 (−2.1%)
silesia/samba 21,606,400 9,102,594 9,061,143 (−0.5%) 8,383,534 (−7.9%) 8,346,076 (−8.3%)
silesia/sao 7,251,944 6,137,755 6,101,747 (−0.6%) 6,136,077 (−0.0%) 6,100,061 (−0.6%)
silesia/webster 41,458,703 18,694,172 18,567,618 (−0.7%) 18,146,641 (−2.9%) 18,010,981 (−3.7%)
silesia/x-ray 8,474,240 7,510,606 7,406,001 (−1.4%) 7,509,449 (−0.0%) 7,404,794 (−1.4%)
silesia/xml 5,345,280 1,681,687 1,672,827 (−0.5%) 1,472,562 (−12.4%) 1,455,641 (−13.4%)

v1.11.1

Choose a tag to compare

@BrianPugh BrianPugh released this 20 Jan 21:37
73b177f

Improvements

  • Javascript:
    • Use bulk memory transfers for WASM data copying. 1.8x faster decomprssion; 1.03x faster compression.
    • Fix memory-leak if an invalid custom dictionary is provided.
    • See #285 for details

Full Changelog: v1.11.0...v1.11.1

v1.11.0

Choose a tag to compare

@BrianPugh BrianPugh released this 19 Jan 23:04
807c55c

Breaking Changes (C Library)

tamp_decompressor_init now requires a window_bits parameter.

Before:

tamp_decompressor_init(&decompressor, NULL, window);

After:

// window_bits specifies the maximum window size the buffer can hold (8-15)
// The buffer must be at least (1 << window_bits) bytes
tamp_decompressor_init(&decompressor, NULL, window, 10);

This change enables runtime validation that the provided window buffer is large enough for the data being decompressed, preventing buffer overflows when decompressing data with a larger window size than expected.

Features

  • C Library: New Stream API - High-level functions for compressing/decompressing data using I/O callbacks. Works with any backend (stdio, LittleFS, FatFs, memory buffers, UART, etc.).

    #include "tamp/compressor.h"
    #include "tamp/common.h"
    
    // Compress a file using stdio
    FILE *in = fopen("input.bin", "rb");
    FILE *out = fopen("output.tamp", "wb");
    unsigned char window[1024];
    TampCompressor compressor;
    
    tamp_compressor_init(&compressor, NULL, window);
    tamp_compress_stream(
        &compressor,
        tamp_stream_stdio_read, in,    // read callback and handle
        tamp_stream_stdio_write, out,  // write callback and handle
        NULL, NULL,                    // optional size outputs
        NULL, NULL                     // optional progress callback
    );
    fclose(in);
    fclose(out);

    Built-in I/O backends (enable via compiler flags):

    Backend Flag Use Case
    Memory -DTAMP_STREAM_MEMORY=1 In-memory compression
    stdio -DTAMP_STREAM_STDIO=1 Desktop/POSIX, ESP-IDF VFS
    LittleFS -DTAMP_STREAM_LITTLEFS=1 Embedded flash filesystems
    FatFs -DTAMP_STREAM_FATFS=1 SD cards, USB storage
  • Performance improvements:

    • 2-3x faster compression on desktop - New platform-optimized find_best_match implementation for x86_64 and aarch64 using SIMD-friendly bit manipulation.
    • Faster compression on embedded targets - Optimized match-finding for Cortex-M and other 32-bit microcontrollers.
    • Faster decompression - Optimized hot path and reduced branch mispredictions.

Full Changelog: v1.10.4...v1.11.0