Fast
Greedy LZ parsing with no entropy stage. Use it when encode latency matters more than maximum density.
VV_MODE_ULTRA_FASTOpen format · compact implementation
VaptVupt is an LZ + tANS compression codec written in C11: zero third-party runtime dependencies, a documented wire format, and byte-exact reference decoders in Python and JavaScript.
Designed for embedders who want a small, inspectable codec boundary—not a universal replacement for every compressor.
01 / Codec
The mode changes how the encoder searches and prices matches. It does not create three incompatible formats: the decoder reads the stream, not the chosen preset.
Greedy LZ parsing with no entropy stage. Use it when encode latency matters more than maximum density.
VV_MODE_ULTRA_FASTThe default. A lazy parser and block-level entropy choices aim for a practical ratio and decode-speed compromise.
VV_MODE_BALANCEDAn optimal-parse, deeper-search path for ratio-first work. Encoding is intentionally slower and can use substantially more memory.
VV_MODE_EXTREME02 / Evidence
The current page profile compares caller-owned contexts in one process across 4, 16 and 64 KiB inputs. The table shows the illustrative 4 KiB synthetic-text subset; the complete run covers 216 profiles and checks every decoded page.
| API | Ratio | Encode p50 µs | Decode p50 µs | Encode MB/s | Decode MB/s | State bytes |
|---|---|---|---|---|---|---|
| VaptVupt FAST caller context | 2.868 | 62.536 | 9.206 | 65.7 | 486.2 | 537,800 |
| LZ4 extState | 2.454 | 12.636 | 2.851 | 339.6 | 1495.0 | 16,416 |
| Zstd context, level 1 | 4.927 | 42.057 | 13.337 | 99.4 | 320.1 | 169,752 |
a14e09f54c2d; Intel Core i7-13700HX, Linux 7.2.3, GCC 14.3, pinned to CPU 4. VaptVupt used its portable scalar path without compiler auto-vectorization; installed LZ4 1.10.0 and Zstd 1.5.7 were single-process userspace libraries. The complete matrix used 64 independent pages, 101 latency samples and seven batch samples per profile. Framing is included and checksums are disabled for all three rows. LZO-RLE and kernel runtime were not available. LZ4 is faster here and Zstd is smaller; this evidence does not establish that VaptVupt supersedes either codec. Full results and reproduction commands.
| Maximum input | Previous | Current | Reduction |
|---|---|---|---|
| 4 KiB | 1,070,264 | 537,800 | 49.75% |
| 16 KiB | 1,131,752 | 574,712 | 49.22% |
| 64 KiB | 1,377,705 | 722,361 | 47.57% |
03 / Build & use
The default build needs GNU Make and a C11 compiler. The codec uses the C standard library and has no third-party runtime dependency; optional threaded encoding is enabled explicitly.
make produces the CLI. make amalg emits a drop-in vaptvupt.c and vaptvupt.h.make test runs C suites, negative cases, and the Python/JavaScript reference checks when their runtimes are available.-w 10..24 selects 1 KiB through 16 MiB; zero/omitted keeps automatic selection..zupt by default and still recognizes legacy .vv frames by their header.git clone https://codeberg.org/berkeley/vaptvupt-codec.git
cd vaptvupt-codec
git checkout v2.65.11
make
make test
./vaptvupt -c -m fast -o fast.zupt input
./vaptvupt -c -m balanced -o data.zupt input
./vaptvupt -c -m extreme -o dense.zupt input
./vaptvupt -d -o restored data.zupt
#include "vaptvupt.h"
vv_options_t opt;
vv_default_options(&opt);
opt.mode = VV_MODE_BALANCED;
size_t cap = vv_compress_bound(src_len);
int64_t n = vv_compress(src, src_len, dst, cap, &opt);
if (n < 0) { /* handle VV_ERR_* */ }
int64_t m = vv_decompress(dst, (size_t)n, out, out_cap);
if (m < 0) { /* reject the frame */ }
vv_cstream_* accepts source chunks up to 1 MiB and preserves match history. vv_dstream_* accepts arbitrary compressed chunks and buffers partial blocks. Keep the same output-buffer base and full-frame capacity across every decode call; written stays cumulative, including calls after completion, while consumed is per call. Release 2.65.11 retains the reset fix from 2.65.10 and adds checked footer, checksum-tail and decoder-span boundaries; valid encoded bytes remain compatible.
04 / Format & filters
A frame starts with a 16-byte header, continues with independently typed blocks, and may end with an XXH64 footer. The public specification is sufficient to write a decoder without importing the C implementation.
Optional reversible BCJ preprocessing can normalize x86 branch targets or AArch64 BL/ADRP instructions before compression. It can improve executable-code ratio on suitable binaries; it is not encryption and does not change the security boundary.
# x86 executable code
./vaptvupt -c -m extreme --bcj -o app.zupt app
# AArch64 executable code
./vaptvupt -c -m extreme --bcj-arm64 -o app.zupt app
# Detect ELF / PE / Mach-O and select one or none
./vaptvupt -c --auto-filter -o app.zupt app
The explicit x86 and ARM64 filters are mutually exclusive. Encoder entry points reject contradictory filter flags and invalid compression-mode values. The CLI also rejects unknown mode names and malformed numeric options.
05 / Boundaries
Compression belongs inside a larger trust design. Treat the frame and its checksum according to what they actually provide.
The optional XXH64 footer detects accidental corruption. It is not a cryptographic authenticator and an attacker can forge it. A .zupt frame alone provides neither confidentiality nor authentication; wrap it in an AEAD or another authenticated envelope when tampering matters.
Allocate from trusted limits, pass the real destination capacity, and reject any negative decoder return. Do not attempt recovery inside a malformed frame.
VV_DECOMPRESS_SKIP_CHECKSUM is appropriate only when an outer authenticated layer has already verified the compressed bytes.
Extreme mode is ratio-first and can consume substantial CPU and matcher memory. Put size, memory, and time limits around attacker-controlled encoding work.
06 / v2.65.11
This release improves page-sized setup, makes literal-table workspace ownership explicit and tightens pointer boundaries. The wire layout and existing public entry points remain compatible.
A caller-owned FAST context covers independent inputs through 64 KiB with no hot-path heap allocation. It resets history on every call and preserves the corresponding one-shot bytes. Its 4 KiB workspace is still 537,800 bytes, too large for a credible per-CPU zram proposal.
Checked Huffman and ANS literal helpers accept aligned caller storage. S/T blocks reuse their existing 48 KiB sequence arena, and direct ANS table construction removes a 4 KiB spread array from individual decoder frames. Whole-frame decode still allocates.
Footer capacity, checksum tails, input spans and both AVX2 prefetch histories are checked before the related pointer is advanced or formed. Fast plus format_v2 now retains the plain-token four-byte minimum match instead of emitting invalid data.
SIMD=0 disables codec intrinsics and dispatch. make scalar-test runs eleven userspace suites. This is not a kernel build: GPL-2.0-only compatibility, libc removal, smaller context memory, KUnit and runtime integration remain unresolved gates.
07 / Primary sources
Specifications, security notes, measurements, and independent decoders live beside the implementation. Release 2.65.11 is mirrored across all four project forges.