Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
e5d9ac0
Add match-finder experiment knobs; measure SWAR variants on STM32H7B0
BrianPugh Jul 15, 2026
de07f4f
Add first-byte-prefilter match finder, default on ARMv7E-M
BrianPugh Jul 15, 2026
06b159c
Speed up decompressor hot paths on non-Cortex-M0 targets
BrianPugh Jul 15, 2026
869c4cc
Update benchmark rows and docs for the M7 optimization results
BrianPugh Jul 15, 2026
42f257a
Move architecture-specific variants out of the main C sources
BrianPugh Jul 15, 2026
93a4d80
Document the variant-file convention in CLAUDE.md
BrianPugh Jul 15, 2026
2ca0a4d
Make core C sources self-contained; drop the variant-file split
BrianPugh Jul 15, 2026
98e3cc1
Scope decompressor fast paths to ARMv7E-M after ESP32-S3 measurement
BrianPugh Jul 15, 2026
e8edc7f
Centralize platform tuning in common.h; whole-function variant selection
BrianPugh Jul 15, 2026
1f53884
Trim STM32H7B0 benchmark rows to default + generic fallback
BrianPugh Jul 15, 2026
6067c49
Label benchmark rows so dash consistently means the default build
BrianPugh Jul 15, 2026
c3c81fc
Make all platform optimizations explicit opt-in, mirroring TAMP_ESP32
BrianPugh Jul 15, 2026
9bdf1b6
Reject conflicting find_best_match selections at compile time
BrianPugh Jul 15, 2026
507b45a
Document why EXTEND_MATCH must stay a macro
BrianPugh Jul 15, 2026
565a665
Replace EXTEND_MATCH macros with a shared static inline function
BrianPugh Jul 15, 2026
a4705bc
Fix stale benchmark preamble: build systems opt in, Tamp does not sel…
BrianPugh Jul 15, 2026
503129d
Benchmark options column lists reproduce-flags, not default/non-default
BrianPugh Jul 15, 2026
200d702
Re-measure RP2040 C row; fix runner DTR for pico-sdk USB-CDC
BrianPugh Jul 15, 2026
f37c90c
Update stale RP2040 C row in BENCHMARKS.md
BrianPugh Jul 16, 2026
7b1569d
Speed up decompressor hot loop: drop dead compare, defer output accou…
BrianPugh Jul 16, 2026
10cfef0
Add QEMU-based embedded decompression profiler (tools/qemu-profiler)
BrianPugh Jul 16, 2026
8cf2356
Speed up decompressor: snapshot window updates, fast decode loop
BrianPugh Jul 16, 2026
b2da57c
Fuzz decompressor across chunk sizes and all flag configurations
BrianPugh Jul 16, 2026
ef10126
Replay fuzz corpora through real ARM binaries under QEMU
BrianPugh Jul 16, 2026
ed107ca
Speed up decompressor: two-token unroll, history-window mode, fixed-c…
BrianPugh Jul 16, 2026
396bc50
qemu-profiler: count all decode helpers in core metric; add Cortex-M3…
BrianPugh Jul 16, 2026
c2bc596
Re-measure RP2040 fast-loop row after two-token unroll
BrianPugh Jul 16, 2026
83591b5
Re-measure STM32H7B0 ARMV7EM row after unroll + history-window rounds
BrianPugh Jul 16, 2026
6acef73
Speed up decompressor: 64-bit bit-reservoir refill (TAMP_RESERVOIR_RE…
BrianPugh Jul 16, 2026
54f10b3
Re-measure STM32H7B0 ARMV7EM row with reservoir refill
BrianPugh Jul 16, 2026
121fe55
Add code-size column to on-device benchmark table
BrianPugh Jul 16, 2026
0f4e203
Document TAMP_HISTORY_WINDOW's classic-stream scope and size lever
BrianPugh Jul 16, 2026
9c10ba1
Remove TAMP_HISTORY_WINDOW: speedup not worth the flash cost
BrianPugh Jul 17, 2026
7af92f1
Re-measure STM32H7B0 ARMV7EM row after TAMP_HISTORY_WINDOW removal
BrianPugh Jul 17, 2026
4df8b9d
Drop the two-token unroll from the reservoir fast loop: smaller AND f…
BrianPugh Jul 17, 2026
09eb85f
Parameterize RP2040 harness tamp flags; refresh ARMV7EM profile summary
BrianPugh Jul 17, 2026
5c8eea1
RP2040 fastloop row: add TAMP_RESERVOIR_REFILL=1, hardware-verified win
BrianPugh Jul 17, 2026
f232108
Extract the fast decode loop; compile the careful body -Os (TAMP_COMP…
BrianPugh Jul 17, 2026
9007409
Remove TAMP_RESERVOIR_REFILL; the reservoir is the only fast-loop imp…
BrianPugh Jul 17, 2026
4e1763a
Apply code-review fixes: guard gap, test coverage, dedup, tooling
BrianPugh Jul 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,9 @@ jobs:
- name: Run C tests (embedded find_best_match)
run: make c-test-embedded

- name: Run C tests (prefilter find_best_match)
run: make c-test-prefilter

- name: Verify CLI compression/decompression integrity
run: |
source .venv/bin/activate
Expand Down
40 changes: 35 additions & 5 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,13 @@ different platforms:
- `compressor.h/c` - Compression implementation (sink/poll low-level API and
higher-level compress/flush API)
- `decompressor.h/c` - Decompression implementation
- `compressor_find_match_desktop.c` - Desktop-optimized match finding (included
by `compressor.c` on 64-bit targets: x86_64, aarch64, unless
`TAMP_USE_EMBEDDED_MATCH=1`)
- `common.c`/`compressor.c`/`decompressor.c` must compile standalone with only
the headers (users vendor these three files), so every implementation
reachable on embedded targets is defined inline. Only variants unreachable
there may live in `#include`'d files (`compressor_find_match_desktop.c` on
`x86_64`/`aarch64`, `compressor_find_match_swar32.c` opt-in) or come from a
platform component ESP32-style (extern `find_best_match`,
`private/tamp_copy.h`).

## Development Commands

Expand Down Expand Up @@ -234,8 +238,34 @@ make website-clean # Clean website build artifacts
(default: 32 bytes, 256+ recommended for performance)
- `TAMP_STREAM_MEMORY` / `TAMP_STREAM_STDIO` / `TAMP_STREAM_LITTLEFS` /
`TAMP_STREAM_FATFS` - Enable built-in I/O handlers for specific backends
- `TAMP_USE_EMBEDDED_MATCH=1` - Force embedded `find_best_match` implementation
on desktop (for testing)
- Platform tuning flags (see `common.h`'s "Platform performance tuning"
section): the core sources never select architecture-specific code on their
own - every flag defaults to the portable implementation, and each build
system opts into its platform's measured configuration (`setup.py` sets
`TAMP_USE_DESKTOP_MATCH=1` on 64-bit hosts, espidf Kconfig defaults
`TAMP_ESP32=y`, the STM32H7B0 harness sets `TAMP_ARMV7EM=1`):
- `TAMP_ARMV7EM=1` - profile for Cortex-M4/M7: enables the prefilter match
finder plus all six decompressor fast-path flags below (measured on
STM32H7B0/M7 vs the portable build: 1.31x compression, 1.92x decompression,
~5.2 KB additional flash; M4 unmeasured on hardware)
- `TAMP_USE_EMBEDDED_MATCH=1` - the portable `find_best_match` (selections are
mutually exclusive, including `TAMP_ESP32`; conflicts are a compile error)
- `TAMP_USE_PREFILTER_MATCH` - first-byte prefilter (slower on 64-bit hosts)
- `TAMP_USE_DESKTOP_MATCH` - 64-bit SWAR for 64-bit hosts
- `TAMP_USE_SWAR32_MATCH` - experimental 32-bit SWAR (candidate for
single-issue cores like Cortex-M33)
- `TAMP_FAST_WINDOW_COPY` - no-wrap fast path in `tamp_window_copy` (+14%
decompression on M7; -3% Xtensa LX7, +160B Cortex-M0+)
- `TAMP_FAST_BIT_REFILL` - locals-based `refill_bit_buffer` (+5% decompression
on M7; -3% Xtensa LX7, +324B Cortex-M0+)
- `TAMP_FAST_OUTPUT_COPY` - word-at-a-time copy to the output buffer
- `TAMP_WINDOW_FROM_OUTPUT` - window update sourced from the just-written
output snapshot instead of `tamp_window_copy`
- `TAMP_FAST_DECODE_LOOP` - checked-once fast inner decode loop over a 64-bit
bit reservoir (the largest single decompression win)
- `TAMP_COMPACT_CAREFUL_BODY` - compile the non-fast-loop careful body -Os
(GCC-only; only sensible with `TAMP_FAST_DECODE_LOOP`) See `common.h` for
each flag's measured numbers.
- `TAMP_USE_MEMSET=1` - Use libc `memset` (default: 1). Set to `0` for
environments without libc (e.g. MicroPython native modules).

Expand Down
99 changes: 95 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ help-main:
@echo " make test Run Python and MicroPython tests"
@echo " make c-test Run C unit tests"
@echo " make c-test-embedded Run C unit tests with embedded find_best_match"
@echo " make c-test-prefilter Run C unit tests with prefilter find_best_match"
@echo " make clean Clean all build artifacts"
@echo ""
@echo "MicroPython native module:"
Expand All @@ -29,10 +30,12 @@ help-extra:
@echo "Fuzzing (requires LLVM clang; on macOS: brew install llvm):"
@echo " make fuzz-decompressor Fuzz decompressor with random input"
@echo " make fuzz-round-trip Fuzz compress->decompress round-trip"
@echo " make fuzz-matrix Short decompressor fuzz of every flag configuration"
@echo " make fuzz-clean Clean fuzz artifacts and corpora"
@echo ""
@echo "Other targets:"
@echo " make binary-size Show binary sizes for README table"
@echo " make benchmark-code-sizes Reproduce the BENCHMARKS.md 'Code size (B)' column"
@echo " make v1-compressed-datasets Regenerate ground-truth v1 (--no-extended) .tamp binaries"
@echo " make extended-compressed-datasets Regenerate ground-truth extended .tamp binaries"
@echo " make c-benchmark-stream Benchmark stream API with various temporary working buffer sizes"
Expand Down Expand Up @@ -408,6 +411,11 @@ CTEST_DEFINES = -DTAMP_STREAM_STDIO=1 -DTAMP_STREAM_MEMORY=1 \
-DTAMP_STREAM_FATFS=1 -DTEST_FATFS=1 \
-DTAMP_LAZY_MATCHING=1 \
-DLFS_NO_DEBUG -DLFS_NO_WARN -DLFS_NO_ERROR
# c-test covers the same match finder the pip/Cython build opts into on
# 64-bit hosts (the core defaults to the portable one); c-test-embedded
# covers the portable path. Selections are mutually exclusive (compile
# error), so this is applied only to the non-embedded tamp objects.
CTEST_MATCH_DEFINE = -DTAMP_USE_DESKTOP_MATCH=1
CTEST_CFLAGS = $(CTEST_INCLUDES) $(CTEST_SANITIZER_FLAGS) $(CTEST_DEFINES)
# Strict warnings applied only to first-party tamp sources, not third-party (Unity/LittleFS/FatFs)
CTEST_WARN_FLAGS = -Wall -Wextra -Wtype-limits -Werror
Expand Down Expand Up @@ -439,7 +447,7 @@ CTEST_TEST_OBJS = \
# Build tamp source files for testing
build/ctests/%.o: tamp/_c_src/tamp/%.c
@mkdir -p build/ctests
$(CTEST_CC) $(CTEST_CFLAGS) $(CTEST_WARN_FLAGS) -c $< -o $@
$(CTEST_CC) $(CTEST_CFLAGS) $(CTEST_MATCH_DEFINE) $(CTEST_WARN_FLAGS) -c $< -o $@

# Build Unity framework
build/unity/unity.o: ctests/Unity/src/unity.c ctests/Unity/src/unity.h
Expand Down Expand Up @@ -475,20 +483,62 @@ build/ctests/fatfs_ramdisk.o: ctests/fatfs_ramdisk.c
# Build test runner (includes test files via #include)
build/ctests/test_runner.o: ctests/test_runner.c ctests/test_compressor.c ctests/test_decompressor.c ctests/test_stream.c ctests/test_stream_filesystems.c
@mkdir -p build/ctests
$(CTEST_CC) $(CTEST_CFLAGS) -c $< -o $@
$(CTEST_CC) $(CTEST_CFLAGS) $(CTEST_MATCH_DEFINE) -c $< -o $@

# Link test executable
build/test_runner: $(CTEST_TAMP_OBJS) $(CTEST_LFS_OBJS) $(CTEST_FATFS_OBJS) $(CTEST_TEST_OBJS)
$(CTEST_CC) $(CTEST_LDFLAGS) -o $@ $^

c-test: build/test_runner
c-test: build/test_runner c-compile-matrix
./build/test_runner

# Compile the vendored trio under every documented decompressor flag
# combination. Regression guard: flag-gated code paths must always compile
# (e.g. TAMP_FAST_DECODE_LOOP=1 with TAMP_EXTENDED=0 once referenced the
# extended-only token_state field and only broke in that combination).
C_COMPILE_MATRIX_CONFIGS = \
"" \
"-DTAMP_ARMV7EM=1" \
"-DTAMP_FAST_DECODE_LOOP=1" \
"-DTAMP_WINDOW_FROM_OUTPUT=1" \
"-DTAMP_EXTENDED=0" \
"-DTAMP_EXTENDED=0 -DTAMP_FAST_DECODE_LOOP=1" \
"-DTAMP_EXTENDED=0 -DTAMP_ARMV7EM=1" \
"-DTAMP_ARMV7EM=1 -DTAMP_COMPACT_CAREFUL_BODY=0" \
"-DTAMP_FAST_DECODE_LOOP=1 -DTAMP_COMPACT_CAREFUL_BODY=1" \
"-DTAMP_USE_MEMSET=0" \
"-DTAMP_STREAM=0" \
"-DTAMP_FIXED_WINDOW_BITS=10 -DTAMP_FIXED_LITERAL_BITS=8" \
"-DTAMP_FIXED_WINDOW_BITS=10 -DTAMP_FIXED_LITERAL_BITS=8 -DTAMP_ARMV7EM=1"

.PHONY: c-compile-matrix
c-compile-matrix:
@mkdir -p build
@set -e; for cfg in $(C_COMPILE_MATRIX_CONFIGS); do \
echo "c-compile-matrix: $$cfg"; \
for src in tamp/_c_src/tamp/common.c tamp/_c_src/tamp/compressor.c tamp/_c_src/tamp/decompressor.c; do \
$(CC) -O2 -Wall -Itamp/_c_src $$cfg -c $$src -o build/c_compile_matrix.o.tmp; \
done; \
done; rm -f build/c_compile_matrix.o.tmp
@set -e; for cfg in \
"-DTAMP_ESP32=1 -DTAMP_USE_DESKTOP_MATCH=1" \
"-DTAMP_USE_EMBEDDED_MATCH=1 -DTAMP_USE_DESKTOP_MATCH=1"; do \
echo "c-compile-matrix (must NOT compile): $$cfg"; \
if $(CC) -O2 -Wall -Itamp/_c_src $$cfg -c tamp/_c_src/tamp/common.c \
-o build/c_compile_matrix.o.tmp 2>/dev/null; then \
echo "c-compile-matrix: ERROR: conflicting match selection compiled: $$cfg"; \
rm -f build/c_compile_matrix.o.tmp; exit 1; \
fi; \
done; rm -f build/c_compile_matrix.o.tmp
@echo "c-compile-matrix: all configurations compile"

clean-c-test:
@rm -f build/test_runner
@rm -f build/test_runner_embedded
@rm -f build/test_runner_prefilter
@rm -f build/ctests/*.o
@rm -f build/ctests-embedded/*.o
@rm -f build/ctests-prefilter/*.o
@rm -f build/unity/*.o

# Embedded implementation tests (forces embedded find_best_match on desktop)
Expand Down Expand Up @@ -517,6 +567,34 @@ build/test_runner_embedded: $(CTEST_EMBEDDED_TAMP_OBJS) $(CTEST_EMBEDDED_TEST_OB
c-test-embedded: build/test_runner_embedded
./build/test_runner_embedded

# Prefilter implementation tests (forces the ARMV7EM profile's find_best_match
# on desktop; without this leg the shipping M4/M7 matcher is compile-checked
# but never behaviorally run on host).
.PHONY: c-test-prefilter

CTEST_PREFILTER_TAMP_OBJS = \
build/ctests-prefilter/common.o \
build/ctests-prefilter/compressor.o \
build/ctests-prefilter/decompressor.o

CTEST_PREFILTER_TEST_OBJS = \
build/unity/unity.o \
build/ctests-prefilter/test_runner.o

build/ctests-prefilter/%.o: tamp/_c_src/tamp/%.c
@mkdir -p build/ctests-prefilter
$(CTEST_CC) $(CTEST_CFLAGS) $(CTEST_WARN_FLAGS) -DTAMP_USE_PREFILTER_MATCH=1 -c $< -o $@

build/ctests-prefilter/test_runner.o: ctests/test_runner.c ctests/test_compressor.c ctests/test_decompressor.c
@mkdir -p build/ctests-prefilter
$(CTEST_CC) $(CTEST_CFLAGS) -DTAMP_USE_PREFILTER_MATCH=1 -c $< -o $@

build/test_runner_prefilter: $(CTEST_PREFILTER_TAMP_OBJS) $(CTEST_PREFILTER_TEST_OBJS) $(CTEST_LFS_OBJS) $(CTEST_FATFS_OBJS)
$(CTEST_CC) $(CTEST_LDFLAGS) -o $@ $^

c-test-prefilter: build/test_runner_prefilter
./build/test_runner_prefilter


############
# Fuzzing
Expand Down Expand Up @@ -558,9 +636,18 @@ fuzz-round-trip: build/fuzz_round_trip
@mkdir -p fuzz/corpus_round_trip
./build/fuzz_round_trip fuzz/corpus_round_trip

# Builds the malicious-input decompressor fuzzer in every flag-gated code-path
# configuration (portable, ARMV7EM profile, fast-loop-only, ESP32, extended
# off, memset off, ...), replays the shared corpus, and fuzzes each briefly.
# FUZZ_MATRIX_SECONDS overrides the per-config fuzz duration (default 90).
.PHONY: fuzz-matrix
fuzz-matrix:
@mkdir -p fuzz/corpus_decompressor
FUZZ_CC=$(FUZZ_CC) fuzz/fuzz-matrix.sh $(or $(FUZZ_MATRIX_SECONDS),90)

fuzz-clean:
@rm -f build/fuzz_decompressor build/fuzz_round_trip
@rm -rf fuzz/corpus_decompressor fuzz/corpus_round_trip
@rm -rf fuzz/corpus_decompressor fuzz/corpus_round_trip build/fuzz_matrix
@rm -rf build/esp32_host build/fuzz_round_trip_esp32 build/esp32_host_differential fuzz/corpus_round_trip_esp32

##################################
Expand Down Expand Up @@ -763,6 +850,10 @@ binary-size:
@output=$$($(MAKE) -s mpy-native-size 2>&1) && echo "$$output" || echo "Tamp (MicroPython Native) (requires MPY_DIR)"
@output=$$($(MAKE) -s c-size 2>&1) && echo "$$output" || echo "Tamp (C) (requires arm-none-eabi-gcc)"

.PHONY: benchmark-code-sizes
benchmark-code-sizes:
@tools/benchmark-code-size.sh


##########
# Website
Expand Down
47 changes: 33 additions & 14 deletions devices/BENCHMARKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,33 @@

All rows measure the same workload: compressing and decompressing the **first
100 KB of [enwik8](https://mattmahoney.net/dc/textdata.html)** with a 1 KB
window (`window=10`, `literal=8`). Throughput is input bytes per second for
compression and output bytes per second for decompression. Reproduce with the
`*-device-benchmark` Makefile targets (see the per-device directories here).
window (`window=10`, `literal=8`), in the classic (v1, non-extended) stream
format. Throughput is input bytes per second for compression and output bytes
per second for decompression. Reproduce with the `*-device-benchmark` Makefile
targets (see the per-device directories here).

| Device | Core | Clock | Runtime / build | Tamp options | Compression (s) | Compression (bytes/s) | Decompression (s) | Decompression (bytes/s) |
| ------------------------------------------------------------------------------------- | -------------- | ------- | --------------------------------- | ----------------------- | --------------- | --------------------- | ----------------- | ----------------------- |
| [Raspberry Pi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) (RP2040) | Cortex-M0+ | 125 MHz | C, `-O3` | — | 2.77 | 36,127 | 0.071 | 1,400,600 |
| [Raspberry Pi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) (RP2040) | Cortex-M0+ | 125 MHz | MicroPython v1.26.1 native module | — | 2.90 | 34,510 | 0.102 | 980,392 |
| ESP32 | Xtensa LX6 | 160 MHz | ESP-IDF v6.0.2, `-O2` | — | 1.756 | 56,900 | 0.068 | 1,470,000 |
| ESP32 | Xtensa LX6 | 160 MHz | ESP-IDF v6.0.2, `-O2` | `TAMP_ESP32` | 1.708 | 58,500 | 0.067 | 1,490,000 |
| ESP32-S3 | Xtensa LX7 | 160 MHz | ESP-IDF v6.0.2, `-O2` | — | 1.487 | 67,200 | 0.053 | 1,882,000 |
| ESP32-S3 | Xtensa LX7 | 160 MHz | ESP-IDF v6.0.2, `-O2` | `TAMP_ESP32` (PIE SIMD) | 0.255 | 392,600 | 0.050 | 1,987,000 |
| ESP32-C3 | RISC-V RV32IMC | 160 MHz | ESP-IDF v6.0.2, `-O2` | — | 1.413 | 70,800 | 0.040 | 2,500,000 |
| ESP32-C3 | RISC-V RV32IMC | 160 MHz | ESP-IDF v6.0.2, `-O2` | `TAMP_ESP32` | 0.961 | 104,100 | 0.036 | 2,777,800 |
| STM32H7B0 [^sram] | Cortex-M7 | 280 MHz | C, `-O3`, I+D cache | — | 0.518 | 192,900 | 0.017 | 5,907,000 |
The "Tamp options" column lists the compile-time flags that reproduce that build
when using Tamp as a library (`—` = none: the portable defaults). The available
flags are documented in the platform tuning section of
`tamp/_c_src/tamp/common.h`; `TAMP_ESP32=1` additionally requires the espidf
component's platform sources.

"Code size (B)" [^codesize] is the sum of `text` (includes `.rodata`) across the
vendored objects, built with that row's exact flags.

| Device | Core | Clock | Runtime / build | Tamp options | Code size (B) | Compression (s) | Compression (bytes/s) | Decompression (s) | Decompression (bytes/s) |
| ------------------------------------------------------------------------------------- | -------------- | ------- | --------------------------------- | ------------------------- | ------------- | --------------- | --------------------- | ----------------- | ----------------------- |
| [Raspberry Pi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) (RP2040) | Cortex-M0+ | 125 MHz | C, `-O3` | — | 6,655 | 2.25 | 44,523 | 0.081 | 1,234,004 |
| [Raspberry Pi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) (RP2040) | Cortex-M0+ | 125 MHz | C, `-O3` | `TAMP_FAST_DECODE_LOOP=1` | 7,387 | 2.25 | 44,523 | 0.059 | 1,700,420 |
| [Raspberry Pi Pico](https://www.raspberrypi.com/products/raspberry-pi-pico/) (RP2040) | Cortex-M0+ | 125 MHz | MicroPython v1.26.1 native module | — | 5,883 | 2.90 | 34,510 | 0.102 | 980,392 |
| ESP32 | Xtensa LX6 | 160 MHz | ESP-IDF v6.0.2, `-O2` | — | 6,581 | 1.756 | 56,900 | 0.068 | 1,470,000 |
| ESP32 | Xtensa LX6 | 160 MHz | ESP-IDF v6.0.2, `-O2` | `TAMP_ESP32=1` | 8,374 | 1.708 | 58,500 | 0.067 | 1,490,000 |
| ESP32-S3 | Xtensa LX7 | 160 MHz | ESP-IDF v6.0.2, `-O2` | — | 6,609 | 1.487 | 67,200 | 0.051 | 1,977,000 |
| ESP32-S3 | Xtensa LX7 | 160 MHz | ESP-IDF v6.0.2, `-O2` | `TAMP_ESP32=1` (PIE SIMD) | 8,458 | 0.255 | 392,600 | 0.048 | 2,066,000 |
| ESP32-C3 | RISC-V RV32IMC | 160 MHz | ESP-IDF v6.0.2, `-O2` | — | 7,215 | 1.413 | 70,800 | 0.040 | 2,500,000 |
| ESP32-C3 | RISC-V RV32IMC | 160 MHz | ESP-IDF v6.0.2, `-O2` | `TAMP_ESP32=1` | 10,561 | 0.961 | 104,100 | 0.036 | 2,777,800 |
| STM32H7B0 [^sram] | Cortex-M7 | 280 MHz | C, `-O3`, I+D cache | — | 6,339 | 0.518 | 192,900 | 0.015 | 6,746,000 |
| STM32H7B0 [^sram] | Cortex-M7 | 280 MHz | C, `-O3`, I+D cache | `TAMP_ARMV7EM=1` | 10,687 | 0.395 | 253,000 | 0.008 | 12,875,000 |

[^sram]:
The STM32H7B0's benchmark input/reference data resides in internal SRAM (the
Expand All @@ -25,5 +37,12 @@ compression and output bytes per second for decompression. Reproduce with the
internal flash. This makes the data-read path somewhat faster than a
flash-resident workload would be.

[^codesize]:
Berkeley `size`'s `text` for `common.o + compressor.o + decompressor.o`
(plus `compressor_esp32.o`, the espidf component's platform source, for
`TAMP_ESP32=1` rows), compiled standalone with that row's CPU/opt/flags - no
linking, no `--gc-sections`. Reproduce with `tools/benchmark-code-size.sh`
(also `make benchmark-code-sizes`).

New device targets (e.g. RP2350, STM32H7) should add rows here using the same
100 KB enwik8 workload and a 10-bit window.
Loading
Loading