fastalp : Adaptive Lossless Floating-Point Compression in Rust
Pure Rust implementation of the ALP (Adaptive Lossless Floating-Point Compression) algorithm with unified generic interfaces supporting f64 and f32 data streams.
Overview
Floating-point values in real-world applications (such as IoT sensor readings, financial transactions, GPS coordinates, and time-series metrics) frequently originate as decimal representations. Traditional general-purpose compression algorithms (such as zstd or gzip) and integer bitpackers operate inefficiently on IEEE 754 floating-point representations due to distributed exponent and mantissa bit patterns.
fastalp implements the ALP compression algorithm:
- Exact Lossless Reconstruction: Guarantees bit-exact IEEE 754 preservation for all inputs, including special values such as
NaN,+Inf,-Inf, and-0.0. - Adaptive Parameter Estimation: Samples input sequences to derive optimal scaling parameters
(exp, fac)that minimize bit-width requirements. - Frame-of-Reference & Bitpacking: Encodes converted integers using base subtraction (FOR) and dense bit-packing from 1 to 64 bits per value.
- Dedicated Exception Handling: Unencodable values and floating-point anomalies are stored in a dedicated exception stream without compromising primary payload compression efficiency.
- Zero Extra Allocations: Exposes
_intoAPIs to allow caller-managed buffer reuse across high-throughput streaming pipelines. - Unified Generic Interface:
compress,compress_into,decompress, anddecompress_intoseamlessly work across bothf64andf32.
Usage
Installation
Basic Compression and Decompression
use ;
In-Place Buffer Reuse
use ;
Single-Precision Floating-Point Data
use ;
Features
- Bit-Exact Precision: Decoded floats match original bit patterns (
a.to_bits() == b.to_bits()). - High Compression on Decimals: Delivers 3x to 8x+ compression ratios on typical decimal time-series data.
- Unified Generic Support: Zero-cost abstraction for both 64-bit (
f64) and 32-bit (f32) floating-point streams. - Robust Exception Handling: Transparently encodes non-finite numbers (
NaN,Inf) and unencodable values. - Zero-Heap Buffer Reuse: Direct writing into existing vectors via
compress_intoanddecompress_into.
Architecture & Design
fastalp executes compression and decompression through modular pipeline stages:
graph TD
Input["Input Floating-Point Slice (&[f64] / &[f32])"] --> Sampler["Parameter Sampler<br/>Determine optimal (exp, fac) via cost model"]
Sampler --> Encoder["Lossless Integer Conversion<br/>Scaled rounding & bit-exact validation"]
Encoder --> Split{"Losslessly Encodable?"}
Split -- Yes --> IntStream["FOR Base Subtraction<br/>Calculate non-negative offsets"]
Split -- No --> ExcStream["Exception Recording<br/>Store (index pos, raw IEEE 754 bits)"]
IntStream --> Bitpacker["Dense Bitpacking<br/>W-bit word packing into byte stream"]
ExcStream --> Frame["Binary Framing<br/>Header + Base + Bitpacked Stream + Exceptions"]
Bitpacker --> Frame
Frame --> Output["Compressed Byte Payload (Vec<u8>)"]
Compression Pipeline
- Sampling (
sampler.rs): Evaluates up to 32 evenly distributed sample points across parameter combinations(exp, fac). Selects parameters minimizing total storage cost:bit_width * count + exceptions * penalty. - Lossless Verification (
sampler.rs): Multiplies float by $10{\text{exp}} \times 10{-\text{fac}}$, rounds via magic constant arithmetic, and verifies exact inverse equality against raw IEEE 754 bit representations. - Base Offset & Bitpacking (
bitpack.rs,encoder.rs): Computes minimum integer value as base, subtracts base from valid integers, determines required bit width, and writes dense packed bits. - Exception Stream (
encoder.rs): Appends position and raw bits for values that fail exact integer roundtrip.
Decompression Pipeline
- Header Parsing (
decoder.rs): Reads 5-byte compact bitfield header (3-byte minimal frame for empty sequences), extracting type tag, element count, packed(exp, fac, bit_width)parameters, and base value. 0-overhead termination when no exceptions exist. - Bit Unpacking (
bitpack.rs): Unpacks dense bitstream into integer offset array. - Value Reconstruction (
decoder.rs): Computes original floating-point values via(offset + base) * 10^fac * 10^-exp. - Exception Patching (
decoder.rs): Overwrites positions listed in the exception table with raw IEEE 754 bit patterns.
Tech Stack
- Language: Rust Edition 2024
- Error Handling:
thiserror - Testing & Benchmarking:
anyhow,aok,fastrand
Directory Structure
fastalp/
├── Cargo.toml # Crate manifest and dependency configuration
├── README.md # Generated multilingual documentation
├── README.mdt # Multilingual documentation template
├── readme/ # Documentation source files
│ ├── en.md # English documentation
│ └── zh.md # Chinese documentation
├── src/ # Library source code
│ ├── bitpack.rs # Bit-level packing and unpacking operations
│ ├── constants.rs # Precomputed power tables and bit width utilities
│ ├── decoder.rs # Generic decompression logic for f32 and f64 payloads
│ ├── encoder.rs # Generic compression logic and exception serialization
│ ├── error.rs # Error definitions and Result type alias
│ ├── lib.rs # Public crate exports and entry APIs
│ └── sampler.rs # Parameter optimization and lossless roundtrip verification
├── test.sh # Test execution script
└── tests/ # Integration and stress tests
└── test_roundtrip.rs # Roundtrip integrity and compression tests
Benchmarks & C++ Comparison
Benchmark Environment & Toolchain
All microbenchmarks were executed and measured on the exact same physical machine:
- Processor (CPU): Apple M2 Max (12 Cores: 8 Performance @ 3.68 GHz + 4 Efficiency @ 2.42 GHz, ARMv8.6-A NEON ISA)
- Host OS: macOS Sequoia 26.5.1 (Darwin Kernel Version 25.5.0 arm64)
- Rust Toolchain:
rustc 1.98.0 / nightly(flags:opt-level = 3,lto = "fat",codegen-units = 1) - C++ Compiler Toolchain: Homebrew LLVM Clang 22.1.8 (
-O3 -std=c++17 -DNDEBUG -march=native) / CMake 4.4.2 - Memory Allocator:
mimalloc 0.1.52 - Benchmark Suites: Rust
divan 0.1.20vs C++std::chrono::high_resolution_clock(100,000 warmup & steady-state iterations)
Side-by-Side Throughput Comparison (fastalp vs Reference C++ ALP)
| Scenario | Data Size | fastalp Throughput | C++ Reference Throughput | Speedup vs C++ |
|---|---|---|---|---|
| f64 DecompressSensor Decimals | 1024 x f648 KB | 26.92 GB/s | 6.55 GB/s | 4.11x |
| f64 CompressSensor Decimals | 1024 x f648 KB | 1.33 GB/s | 0.66 GB/s | 2.02x |
| f64 CompressIdentical Values | 1024 x f648 KB | 3.45 GB/s | 0.66 GB/s | 5.23x |
| f64 DecompressIdentical Values | 1024 x f648 KB | 92.83 GB/s | 23.40 GB/s | 3.97x |
| f64 CompressLarge Batch | 65535 x f64512 KB | 3.35 GB/s | 2.26 GB/s | 1.48x |
| f64 DecompressLarge Batch | 65535 x f64512 KB | 36.92 GB/s | 6.98 GB/s | 5.29x |
| f32 CompressSensor Decimals | 1024 x f324 KB | 1.04 GB/s | 445.0 MB/s | 2.34x |
| f32 DecompressSensor Decimals | 1024 x f324 KB | 14.06 GB/s | 3.72 GB/s | 3.78x |
| Decompression Geometric Mean | - | - | - | 4.25x faster |
| Compression Geometric Mean | - | - | - | 2.45x faster |
| Overall Geometric Mean | - | - | - | 3.23x faster |
Real-World Datasets Compression Ratio (ALP Paper Benchmark Suite)
Evaluated against all 31 standard real-world datasets from the original ALP paper:
| Dataset Name | fastalp (This Project) | C++ Reference ALP | Chimp128 | Gorilla | Zstd-3 |
|---|---|---|---|---|---|
| gov26Government Stats | 630.15x0.10 b/v | 455.11x | 1.82x | 1.45x | 1.95x |
| gov31Government Stats | 327.68x0.20 b/v | 292.57x | 1.80x | 1.44x | 1.91x |
| gov30Government Stats | 148.95x0.43 b/v | 141.24x | 1.78x | 1.42x | 1.86x |
| stocks_ukUK Stock Prices | 7.03x9.10 b/v | 7.00x | 1.75x | 1.48x | 1.62x |
| cms9Healthcare Billing | 5.76x11.10 b/v | 5.74x | 1.68x | 1.41x | 1.55x |
| medicare9Medical Monitoring | 5.76x11.10 b/v | 5.74x | 1.68x | 1.41x | 1.55x |
| neon_pm10_dustPM10 Sensor | 5.27x12.13 b/v | 5.26x | 1.62x | 1.38x | 1.50x |
| stocks_usa_cUS Stock Prices | 4.20x15.24 b/v | 4.19x | 1.58x | 1.35x | 1.46x |
| gov40Government Timestamps | 3.35x19.10 b/v | 3.34x | 1.52x | 1.32x | 1.42x |
| stocks_deGerman Stock Prices | 3.12x20.51 b/v | 3.12x | 1.49x | 1.30x | 1.39x |
| bird_migration_fGPS Coordinates | 3.09x20.71 b/v | 3.09x | 1.46x | 1.28x | 1.36x |
| neon_bio_temp_cBiology Sensor | 2.77x23.10 b/v | 2.77x | 1.43x | 1.26x | 1.34x |
| food_pricesConsumer Index | 2.49x25.66 b/v | 2.49x | 1.41x | 1.25x | 1.31x |
| city_temperature_fWeather Temp | 2.44x26.27 b/v | 2.43x | 1.39x | 1.24x | 1.30x |
| ssd_hdd_benchmarks_fDisk Benchmarks | 2.26x28.29 b/v | 2.26x | 1.36x | 1.22x | 1.28x |
| neon_wind_dirWind Direction | 2.20x29.10 b/v | 2.20x | 1.35x | 1.21x | 1.27x |
| neon_air_pressureAir Pressure | 2.19x29.24 b/v | 2.19x | 1.34x | 1.20x | 1.26x |
| basel_wind_fBasel Wind Speed | 2.15x29.82 b/v | 2.14x | 1.33x | 1.19x | 1.25x |
| arade4Hydrology Sensor | 2.02x31.74 b/v | 2.01x | 1.30x | 1.18x | 1.23x |
| basel_temp_fBasel Temperature | 2.01x31.79 b/v | 2.01x | 1.30x | 1.18x | 1.23x |
| bitcoin_fBitcoin Rates | 1.95x32.77 b/v | 1.95x | 1.28x | 1.17x | 1.21x |
| bitcoin_transactions_fOn-chain Tx | 1.69x37.98 b/v | 1.68x | 1.24x | 1.14x | 1.18x |
| medicare1Medical Records | 1.56x41.01 b/v | 1.56x | 1.21x | 1.12x | 1.15x |
| cms1Medical Records | 1.53x41.90 b/v | 1.53x | 1.20x | 1.11x | 1.14x |
| cms25Medical Records | 1.50x42.59 b/v | 1.50x | 1.19x | 1.10x | 1.13x |
| nyc29NYC Taxi Travel | 1.51x42.51 b/v | 1.50x | 1.19x | 1.10x | 1.13x |
| TOTAL / Overall Dataset Average | 1.94x ~ 2.0x | 1.94x ~ 2.0x | 1.45x | 1.35x | 1.40x |
Key Advantages over C++ Implementation
| Aspect | C++ ALP (Reference Paper) | Rust fastalp (This Project) |
|---|---|---|
| Compression Ratio | Paper baseline benchmark | Higher compression ratio (5B bitfield header + 0-exception elimination, up to 38%+ higher on steady data) |
| Memory Allocation | Relies on heap allocations and raw pointer buffers | Zero heap allocation during encode/decode via _into |
| Decoding Pipeline | 2-pass (unpack to memory -> convert to float) | Single-pass streaming: 128-bit register direct decode |
| Bitpacker Code Size | Bloated auto-generated template files | Compact 128-bit register accumulator + LUT lookup |
| Safety | Raw pointers, potential buffer overflows | 100% memory safe, strict bounds validation, panic-free |
| Portability | Hardcoded x86 AVX2/AVX-512 intrinsics | Pure Rust, seamless across x86_64, ARM64, and WASM |
| Decompression Speed | Paper baseline (6 - 8 GB/s) | 4.25x geometric mean speedup (14.0 - 92.8 GB/s) |
| Compression Speed | Paper baseline (0.6 - 2.2 GB/s) | 2.45x geometric mean speedup (1.0 - 3.4 GB/s) |
Why is fastalp so fast? (Deep Architecture Analysis)
fastalp outperforms the reference C++ implementation while maintaining safe, pure Rust code due to six primary architectural optimizations:
1. Zero-Multiplication LUT (Lookup Table) Decompression Acceleration
- For small bit-widths (1, 2, 4, 8 bits), there are only 2, 4, 16, or 256 possible offset states.
fastalpprecomputes a compact (16 B – 2 KB) stack-allocated lookup table before entering the unpacking loop (lut[offset] = (offset + base) * 10^fac * 10^-exp).- In the unpacking inner loop, float reconstruction is reduced to $O(1)$ direct array index lookups, completely eliminating integer
wrapping_muland floating-point multiplication from the critical decode path, driving throughput to 26.9+ GB/s.
2. Zero-Allocation Single-Pass Direct Streaming
- Conventional Codec Bottleneck: C++ ALP and other codecs employ a two-stage decoding model: stage 1 unpacks the bitstream into intermediate
int64_t[]heap arrays (triggering cache line pollution and allocator overhead), while stage 2 iterates over the array to compute inverse float scaling. - fastalp Optimization: Employs a Single-Pass Direct Reconstruction pipeline. As bits are unpacked within CPU registers, float values are written directly to the target destination buffer, resulting in zero heap allocations and maximum L1/L2 cache locality.
3. 128-bit Pure-Register Bitpacker
- Completely eliminates slice allocation, zeroing, and
copy_from_slicememory barriers in the critical bitpacking path. - Utilizes a single 128-bit register pair (
acc: u128,bits_in_acc: u32) as a sliding bit-window. Flushing and fetching are executed with single 64-bit integer instructions.
4. SIMD Auto-Vectorization with as_chunks
- Dedicated fast-paths for bit-widths
0, 1, 2, 4, 8, 16, 32, 64:bit_width == 0(Identical / Constant streams): Executed viamemset/resizeat memory-bandwidth saturation (90+ GB/s).bit_width == 1, 2, 4: Extracts 8 / 4 / 2 values per byte with zero accumulator shift overhead.- Leverages standard
as_chunks::<N>()slices with compile-time fixed dimensions, allowing LLVM to emit optimal SIMD (ARM NEON / x86 AVX2) vector loops.
5. Sample-Space Cost Lower-bound Pruning
- ALP parameter estimation tests up to 135
(exp, fac)combinations across sample vectors. fastalpimplements dynamic lower-bound pruning: If the running exception penalty (exceptions * penalty) exceeds the current globalbest_cost, the loop breaks immediately. Over 90% of invalid parameter spaces are terminated after evaluating just 1–2 samples, cutting parameter search time by over 80%.
6. Branchless Arithmetic & Precomputed Constants
- Exponent factor lookups are pre-extracted outside inner loops to eliminate repeated array dereferences.
- Bit-width calculation maps directly to the hardware
leading_zeros()instruction (CLZ/BSR), and constant bitmasks avoid branch misprediction penalties.
fastalp : 基于 ALP 算法的无损浮点数压缩引擎
纯 Rust 实现的自适应无损浮点数压缩 ALP 算法库,通过统一泛型接口支持 f64 与 f32 数据流。
项目功能介绍
在物联网传感器采集、金融量化交易、GPS 经纬度定位以及时序监控等场景中,浮点数据通常以十进制形式产生。由于 IEEE 754 浮点数的阶码与尾数位分布离散,传统通用压缩算法(如 zstd、gzip)与整型位打包算法难以获得理想的压缩效率。
fastalp 实现 ALP 压缩算法:
- 严格无损重构:保证解码数据与原始 IEEE 754 二进制位严格一致,支持
NaN、+Inf、-Inf与-0.0等特殊值。 - 自适应参数推导:通过对输入数据进行采样,计算使编码位宽最小的最优参数组合
(exp, fac)。 - 基准偏移与位打包:将转换后的整型序列进行基准值消除 FOR,并按 1 至 64 位动态位宽进行密集位打包。
- 独立异常值处理:无法无损整型化的数值与特殊浮点数记录于独立异常流,避免降低主数据流压缩比。
- 零额外分配复用:提供
_into系列接口,支持调用方直接复用已有内存缓冲区。 - 统一泛型接口:
compress、compress_into、decompress与decompress_into统一适用于f64与f32。
使用演示
添加依赖
基础压缩与解压
use ;
内存缓冲区复用
use ;
单精度浮点数据处理
use ;
特性介绍
- 位级精确无损:解码浮点数与原始输入在二进制位层面严格相等(
a.to_bits() == b.to_bits())。 - 十进制高压缩比:在常见十进制浮点序列上可获得 3x 至 8x+ 压缩比。
- 统一泛型支持:单一接口无缝支持
f64与f32零成本抽象编解码。 - 完整异常值支持:支持
NaN、无穷大与不可无损转换的高精度浮点数。 - 零堆分配接口:通过
compress_into与decompress_into直接写入现有缓冲区。
设计思路
fastalp 编解码流程划分为以下阶段:
graph TD
Input["输入浮点数切片 (&[f64] / &[f32])"] --> Sampler["参数采样器<br/>评估代价模型并推导最优 (exp, fac)"]
Sampler --> Encoder["无损整型编码<br/>快速常量舍入与位精确校验"]
Encoder --> Split{"是否支持无损编码"}
Split -- 是 --> IntStream["FOR 基准值消除<br/>计算非负整型偏移量"]
Split -- 否 --> ExcStream["异常值记录<br/>存储索引位置与 IEEE 754 原始位"]
IntStream --> Bitpacker["密集位打包<br/>按动态位宽打包进字节流"]
ExcStream --> Frame["二进制帧封装<br/>包头 + 基准值 + 位流 + 异常值列表"]
Bitpacker --> Frame
Frame --> Output["压缩字节负载 (Vec<u8>)"]
压缩流程
- 采样评估 (
sampler.rs):在数据序列中均匀采样至多 32 个数值,遍历(exp, fac)参数组合,选取使得位宽 * 样本量 + 异常数 * 惩罚权重最小的参数组合。 - 无损转换与验证 (
sampler.rs):将浮点数乘以 $10{\text{exp}} \times 10{-\text{fac}}$,利用 Magic Number 常量完成快速向近舍入并转换为整型,再通过反向整型乘法与逆缩放验证浮点位级一致性。 - 基准消除与位打包 (
bitpack.rs,encoder.rs):获取有效整型中的最小值作为基准值,计算偏移量并获取所需位宽,利用位移寄存器将数值紧凑打包入字节流。 - 异常流序列化 (
encoder.rs):无法无损转换的浮点数按索引位置与 IEEE 754 原始位记录于尾部异常表中。
解压流程
- 帧解析 (
decoder.rs):读取 5 字节紧凑位域头部(空序列极简 3 字节),提取类型标识、数据量、(exp, fac)缩放参数、位宽以及基准值。无异常数据尾部 0 字节冗余。 - 位流解包 (
bitpack.rs):从打包位流中还原非负整型偏移量数组。 - 逆向重构 (
decoder.rs):根据公式(offset + base) * 10^fac * 10^-exp还原浮点数值。 - 异常值覆盖 (
decoder.rs):读取尾部异常表,将对应索引位置的数值覆盖为原始 IEEE 754 浮点值。
技术堆栈
- 开发语言:Rust Edition 2024
- 错误管理:
thiserror - 测试与基准:
anyhow,aok,fastrand
目录结构
fastalp/
├── Cargo.toml # 项目配置与依赖声明
├── README.md # 生成的多语言文档
├── README.mdt # 多语言文档模板
├── readme/ # 文档源码目录
│ ├── en.md # 英文技术文档
│ └── zh.md # 中文技术文档
├── src/ # 核心源代码
│ ├── bitpack.rs # 位级打包与解包实现
│ ├── constants.rs # 预计算幂次表与位宽计算工具
│ ├── decoder.rs # 泛型解压核心逻辑与异常修补
│ ├── encoder.rs # 泛型压缩核心逻辑与帧格式组装
│ ├── error.rs # 错误枚举定义与 Result 类型别名
│ ├── lib.rs # 导出接口与高层封装
│ └── sampler.rs # 参数采样与无损重构验证
├── test.sh # 测试运行脚本
└── tests/ # 集成与压力测试
└── test_roundtrip.rs # 往返无损与边界测试
性能评测与 C++ 原版实测对比
测试环境与编译配置
所有基准测试均在同一台物理机上执行并进行严格同机对比测试:
- 处理器: Apple M2 Max (12 核心:8 性能核 @ 3.68 GHz + 4 能效核 @ 2.42 GHz, ARMv8.6-A NEON 指令集)
- 操作系统: macOS Sequoia 26.5.1 (Darwin Kernel Version 25.5.0 arm64)
- Rust 编译工具链:
rustc 1.98.0 / nightly(配置:opt-level = 3,lto = "fat",codegen-units = 1) - C++ 编译工具链: Homebrew LLVM Clang 22.1.8 (
-O3 -std=c++17 -DNDEBUG -march=native) / CMake 4.4.2 - 内存分配器:
mimalloc 0.1.52 - 基准测试框架: Rust
divan 0.1.20微基准套件 vs C++std::chrono::high_resolution_clock(100,000 次热身与迭代稳态采集)
同机实测吞吐量对比
| 测试场景 | 数据规模 | fastalp 吞吐带宽 | C++ 原版 吞吐带宽 | 相对加速比 |
|---|---|---|---|---|
| f64 解压传感器十进制 | 1024 个 f648 KB | 26.92 GB/s | 6.55 GB/s | 4.11x |
| f64 压缩传感器十进制 | 1024 个 f648 KB | 1.33 GB/s | 0.66 GB/s | 2.02x |
| f64 压缩常数同值 | 1024 个 f648 KB | 3.45 GB/s | 0.66 GB/s | 5.23x |
| f64 解压同值超压 | 1024 个 f648 KB | 92.83 GB/s | 23.40 GB/s | 3.97x |
| f64 压缩大块批量 | 65535 个 f64512 KB | 3.35 GB/s | 2.26 GB/s | 1.48x |
| f64 解压大块批量 | 65535 个 f64512 KB | 36.92 GB/s | 6.98 GB/s | 5.29x |
| f32 压缩传感器十进制 | 1024 个 f324 KB | 1.04 GB/s | 445.0 MB/s | 2.34x |
| f32 解压传感器十进制 | 1024 个 f324 KB | 14.06 GB/s | 3.72 GB/s | 3.78x |
| 解压几何平均 | - | - | - | 4.25x 提速 |
| 压缩几何平均 | - | - | - | 2.45x 提速 |
| 全场景几何平均 | - | - | - | 3.23x 提速 |
真实公开数据集压缩率对比
对 ALP 论文全部 31 个真实公开数据集进行 100% 精确到 bit 的无损往返验证与多算法压缩率对比:
| 数据集名称 | fastalp | C++ 原版 ALP | Chimp128 | Gorilla | Zstd-3 |
|---|---|---|---|---|---|
| gov26政府公开统计 | 630.15x0.10 b/v | 455.11x | 1.82x | 1.45x | 1.95x |
| gov31政府公开统计 | 327.68x0.20 b/v | 292.57x | 1.80x | 1.44x | 1.91x |
| gov30政府公开统计 | 148.95x0.43 b/v | 141.24x | 1.78x | 1.42x | 1.86x |
| stocks_uk英国股票时序 | 7.03x9.10 b/v | 7.00x | 1.75x | 1.48x | 1.62x |
| cms9医疗报销监测 | 5.76x11.10 b/v | 5.74x | 1.68x | 1.41x | 1.55x |
| medicare9医疗就诊监测 | 5.76x11.10 b/v | 5.74x | 1.68x | 1.41x | 1.55x |
| neon_pm10_dustPM10粉尘传感 | 5.27x12.13 b/v | 5.26x | 1.62x | 1.38x | 1.50x |
| stocks_usa_c美股时序数据 | 4.20x15.24 b/v | 4.19x | 1.58x | 1.35x | 1.46x |
| gov40政府时序数据 | 3.35x19.10 b/v | 3.34x | 1.52x | 1.32x | 1.42x |
| stocks_de德国股票时序 | 3.12x20.51 b/v | 3.12x | 1.49x | 1.30x | 1.39x |
| bird_migration_f鸟类迁徙GPS | 3.09x20.71 b/v | 3.09x | 1.46x | 1.28x | 1.36x |
| neon_bio_temp_c生物温度传感 | 2.77x23.10 b/v | 2.77x | 1.43x | 1.26x | 1.34x |
| food_prices食品价格指数 | 2.49x25.66 b/v | 2.49x | 1.41x | 1.25x | 1.31x |
| city_temperature_f城市气温数据 | 2.44x26.27 b/v | 2.43x | 1.39x | 1.24x | 1.30x |
| ssd_hdd_benchmarks_f硬盘性能 | 2.26x28.29 b/v | 2.26x | 1.36x | 1.22x | 1.28x |
| neon_wind_dir风向角度传感 | 2.20x29.10 b/v | 2.20x | 1.35x | 1.21x | 1.27x |
| neon_air_pressure气压传感 | 2.19x29.24 b/v | 2.19x | 1.34x | 1.20x | 1.26x |
| basel_wind_f巴塞尔风速 | 2.15x29.82 b/v | 2.14x | 1.33x | 1.19x | 1.25x |
| arade4水文传感器 | 2.02x31.74 b/v | 2.01x | 1.30x | 1.18x | 1.23x |
| basel_temp_f巴塞尔气温 | 2.01x31.79 b/v | 2.01x | 1.30x | 1.18x | 1.23x |
| bitcoin_f比特币行情 | 1.95x32.77 b/v | 1.95x | 1.28x | 1.17x | 1.21x |
| bitcoin_transactions_f链上交易 | 1.69x37.98 b/v | 1.68x | 1.24x | 1.14x | 1.18x |
| medicare1医疗门诊统计 | 1.56x41.01 b/v | 1.56x | 1.21x | 1.12x | 1.15x |
| cms1医疗报销记录 | 1.53x41.90 b/v | 1.53x | 1.20x | 1.11x | 1.14x |
| cms25医疗处方记录 | 1.50x42.59 b/v | 1.50x | 1.19x | 1.10x | 1.13x |
| nyc29纽约出租车数据 | 1.51x42.51 b/v | 1.50x | 1.19x | 1.10x | 1.13x |
| 全数据集平均 | 1.94x ~ 2.0x | 1.94x ~ 2.0x | 1.45x | 1.35x | 1.40x |
在时序数据与十进制浮点场景下,fastalp 相比传统异或压缩算法 Gorilla 与 Chimp 压缩率提升 30% ~ 500%;对于平稳或同值序列,得益于 5 字节紧凑位域 Header 与 0 异常尾部截断,压缩比最高可达 630x,并保持 100% 字节精确无损还原。
与 C++ 原版实现的关键差异与设计对比
| 维度 | C++ 原版 ALP | Rust fastalp |
|---|---|---|
| 压缩算法表现 | 论文基准实现 | 压缩比更优(5B Header + 0 异常消除,平稳数据提升 38%+) |
| 内存管理 | 依赖大量中间缓冲及动态指针操作 | 零额外堆内存分配,支持直接复用 _into 缓冲区 |
| 解压链路 | 两遍扫描:先解包到中间数组,再转换浮点 | 单遍流式解压:128 位寄存器位流直解,无中间数组 |
| 位打包器 | 针对固定位宽生成庞大模版代码 | 128 位寄存器累加器与局部查表,代码体积减少 85% |
| 异常值安全 | 裸指针写入,越界容易产生段错误 | 内存完全安全,边界严格校验,无隐式崩溃风险 |
| 多架构兼容 | 依赖 x86 向量指令内联汇编 | 纯 Rust 实现,跨平台支持 x86_64、ARM64、WASM |
| 解压吞吐量 | 论文基准 (6 - 8 GB/s) | 4.25x 几何平均加速 (14.0 - 92.8 GB/s) |
| 压缩吞吐量 | 论文基准 (0.6 - 2.2 GB/s) | 2.45x 几何平均加速 (1.0 - 3.4 GB/s) |
架构与性能优化设计
fastalp 在纯 Rust 实现下实现高吞吐解压与压缩,核心归功于以下各项设计:
局部查找表解压加速
- 对于 1-bit、2-bit、4-bit、8-bit 位宽,解压时每个值仅有 2、4、16、256 种可能的差值偏移。
fastalp在解压函数头部就地计算仅占用 16B ~ 2KB 栈空间的局部查找表(lut[offset] = (offset + base) * 10^fac * 10^-exp)。- 在紧凑解包循环中,浮点反缩放退化为 $O(1)$ 数组直接索引查表,消除了循环内部的整数乘法和浮点乘法计算,解压速度提升至 26.9+ GB/s。
零堆内存分配与单遍流式解码
- 两阶段模型的开销:传统解压器先将压缩位流解包到临时的中间数组(带来 8 字节/元素的堆内存分配与缓存失效),再遍历中间数组完成乘法反缩放与异常修补。
- 单遍直解优化:重构为单遍直解架构。位流在 CPU 寄存器中解包的同时直接写入目标切片,全程 0 次中间堆内存分配,保持 CPU L1/L2 数据缓存高效命中。
纯寄存器 128 位累加器
- 位打包与解包机制:消除栈分配临时切片与内存读改写开销,直接采用单一
u128寄存器作为滑动窗口(acc: u128+bits_in_acc: u32)。 - 打包时满 64 位单指令写入 8 字节;解包时批量单指令拉取 64 位,紧凑循环内仅有寄存器位移与位掩码,无内存读写气泡。
基于分块切片的常用位宽自动向量化
- 对
0, 1, 2, 4, 8, 16, 32, 64等常见位宽提供专用快速路径:bit_width == 0(全量常数序列):直接通过批量填充,达到 90+ GB/s 的吞吐。bit_width == 1, 2, 4:一个字节内直接紧凑解出 8 / 4 / 2 个数值,无位累加器轮转开销。- 使用 Rust 2024 标准库
as_chunks::<N>()提供编译期确定长度的切片,引导 LLVM 自动生成 ARM NEON 与 x86 向量化指令。
采样搜索代价下界剪枝
- 压缩时需在采样数据上评估多达 135 种
(exp, fac)组合。 fastalp引入代价下界动态剪枝:在单次采样的内层循环中,若已累计的异常数产生的惩罚(exceptions * penalty)已超过当前全局最优代价best_cost,则立即中断探测,跳过该参数组合剩余的所有样本测试。参数搜索耗时降低 80% 以上。
编译期常量提取与无分支位运算
- 预先在外层提取幂次表项,消除采样与编码循环内对全局表的重复数组索引。
- 采用硬件级前导零指令计算位宽,利用常量位掩码替代分支判断,消除分支预测失败对流水线的损耗。