feat: add SIMD engines (Simd, Avx2, Neon) behind a simd-unsafe feature
Add SIMD-accelerated base64 for the STANDARD and URL_SAFE alphabets, controlled by the `simd-unsafe` feature (off by default). It is the only feature that uses `unsafe`; without it the crate is `#![forbid(unsafe_code)]`. When enabled, `unsafe` is confined to the `engine::simd` module and the crate uses `#![deny(unsafe_code)]`. Three engines are provided, all reusing the scalar `GeneralPurpose` kernels for the tail: - `Simd`: detects the best instruction set at runtime (AVX2 on x86_64, NEON on aarch64) and falls back to the scalar engine. Needs `std` for the detection. - `Avx2` / `Neon`: target one instruction set with no runtime detection, so they work in `no_std`. `Avx2` has checked `standard` / `url_safe` constructors (std) plus `unsafe` `*_unchecked` variants; NEON is mandatory on aarch64 so `Neon`'s constructors are safe. Only the STANDARD and URL_SAFE alphabets are accelerated, so the engines have dedicated `::standard` / `::url_safe` constructors (no `&Alphabet` parameter); the per-alphabet lookup tables are the associated constants of a sealed `SimdAlphabet` trait so the generic kernels can inline them. `GeneralPurpose` stays a pure-scalar engine (also aliased as `Scalar`); the encode/decode helpers take an optional SIMD-prefix step that is a no-op for it, and the scalar encode tail is factored out so it is not monomorphized per engine. Instruction counts below were gathered with gungraun (Callgrind); wall-clock times with the criterion benchmarks (AVX2, x86-64-v3, this machine): | Operation | Input | Instructions (scalar -> SIMD) | Wall-clock (scalar -> SIMD) | | ------------ | ----- | ------------------------------ | --------------------------- | | encode_slice | 3 KiB | 22,245 -> 4,741 (4.7x) | 1.73 us -> 468 ns (3.7x) | | encode_slice | 3 MiB | 22,282,621 -> 3,802,013 (5.9x) | 1.74 ms -> 456 us (3.8x) | | decode_slice | 3 KiB | 28,620 -> 4,817 (5.9x) | 1.49 us -> 230 ns (6.5x) | | decode_slice | 3 MiB | 28,705,264 -> 4,063,989 (7.1x) | 1.54 ms -> 216 us (7.1x) |
M
Martin Taillefer committed
ce2281bb31073bf0e4b8aca47990239574bd3fe1
Parent: 81fa4f1