entropack-alp
v0.8.0
Published
Pure-TypeScript ALP — adaptive lossless floating-point compression for f64/f32 columnar and time-series data (SIGMOD 2024)
Maintainers
Readme
纯 TypeScript 的无损浮点压缩
与 Rust 参考实现逐字节一致——Rust 或 C++ 压出的流,在浏览器里按位精确解出,反之亦然。
English | 简体中文
ALP(Adaptive Lossless floating-Point compression,SIGMOD 2024)的纯 TypeScript 实现。
完整编解码器(编码 + 解码),支持 f64 与 f32,零运行时依赖,Node 与浏览器通吃。
论文
以下论文算法的独立实现:
Azim Afroozeh, Leonardo X. Kuffo, and Peter Boncz. ALP: Adaptive Lossless floating-Point Compression. Proc. ACM Manag. Data 1(4), Article 230, 2023 年 12 月. DOI · 作者自存档(CWI) · C++ 参考
与 CWI 无关联。对已发表算法的独立实现。
跨语言,逐字节一致
这正是本包存在的意义。它读写 ALPF v1 线格式,与 Rust 实现 完全一致, 双向验证:
- 黄金向量——
alp-format/testdata/v1的 11 个共享向量 解码按位精确,且toBytes(compress(input))逐字节复现每个黄金文件 (四种方案 ALP / ALP_rd / 字典 / RLE 全覆盖)。 - 新鲜数据交叉解码——Rust 编码器压出的数据在这里按位精确解出(含 NaN 载荷、 ±0、无穷大、denormal),本包压出的字节在 Rust 侧按位精确解出。五类新鲜随机 数据上,两个编码器产出完全相同的字节。
所以:服务端(Rust/C++)压一次、发送字节、浏览器里解码。
实现内容
- ALP + ALP_rd,
f64与f32双精度(compress/decompress、compressF32/decompressF32)——论文 §3 核心 + §4.4 float32。 - DICT/RLE + ALP 级联(论文 Table 4),面向高重复 / 长运行段列。
- ALPF 线格式(
toBytes/fromBytes)带 CRC-32C;fromBytes对不可信输入 做完整校验(结构封顶、分配防御、精确消费),抛FormatError——绝不崩溃或挂起。 - 确定性:同一输入永远产出相同字节。
无损契约:对任意输入,decompress(compress(data)) 与
decompress(fromBytes(toBytes(compress(data)))) 都按位精确还原 data。由覆盖
完整 64 位与 32 位位模式域的属性测试保证,并经五轮跨语言对抗评审加固
(其中揪出过一个 f32 signaling-NaN 载荷在 JS number 域被静默的 bug——现已在
所有路径改走原始位视图读取)。
压缩率
pnpm bench 实测,与 Rust 实现使用同一批确定性数据集——数字与 alp-rs
逐字一致:
| f64 数据集 | 值数量 | bits/value | 相对 64 位 | |---|---|---|---| | 两位小数价格 | 250,000 | 24.12 | 2.65x | | 存成 double 的整数 | 10,000 | 20.57 | 3.11x | | 常量列 | 5,000 | 0.09 | 727x | | 随机位模式(ALP_rd) | 120,000 | 64.44 | 0.99x | | 价格与随机各半 | 102,400 | 52.05 | 1.23x | | 100 个不同价格乱序(DICT+ALP) | 100,000 | 7.13 | 8.98x | | 长常量运行段(RLE+ALP) | 150,000 | 0.23 | 281x |
| f32 数据集 | 值数量 | bits/value | 相对 32 位 | |---|---|---|---| | 两位小数价格 | 250,000 | 20.10 | 1.59x | | 随机位模式(ALP_rd) | 120,000 | 32.22 | 0.99x | | ML 权重风格(ALP_rd) | 8,192 | 27.00 | 1.19x |
吞吐
纯 JavaScript、单线程,一个 102,400 值的两位小数价格 rowgroup(Apple M 系列、Node 22):
| 操作 | ns/值 | 值/秒 | |---|---|---| | 压缩 | ~223 | ~4.5 M | | 解压 | ~32 | ~32 M |
解压约 256 MB/s 的 double 输出——对交互式与可视化场景绰绰有余。这是一个 正确性优先的纯 TS 编解码器,因此比 NEON 向量化的 Rust 原生参考(~0.36 ns/值) 慢约 90 倍;追求原始吞吐时用 Rust crate。按位宽特化的解包路径、 或同一 API 背后的 Rust→WASM 快路径,是自然的下一步。
快速上手
import { compress, decompress, toBytes, fromBytes } from "entropack-alp";
const data = new Float64Array([8.0605, 1.23, 4.56]);
const c = compress(data);
// 内存态往返
const restored = decompress(c);
// 序列化为跨语言的 ALPF 字节格式
const bytes = toBytes(c); // Uint8Array,alp-rs 可解
const back = decompress(fromBytes(bytes));
// float32
import { compressF32, decompressF32 } from "entropack-alp";
const weights = new Float32Array([0.1, 0.2, 0.3]);
const w = decompressF32(compressF32(weights));测试
pnpm test # 158 个测试:单元 + 一致性 + 属性 + 互操作 + 畸形流
pnpm typecheck
pnpm bench覆盖:镜像 Rust 套件的各模块单测;黄金向量一致性(双向逐字节);Rust↔TS
新鲜数据交叉解码;覆盖完整 u64/u32 位域的属性测试(含 NaN 载荷、±0、
无穷大、denormal);以及畸形流测试(截断、头部损坏、越界字段、恶意计数、
随机翻位)——全部必须抛 FormatError 且不崩溃。
许可证
Apache-2.0。
