| 1 |
`crc-fast` |
| 2 |
=========== |
| 3 |
|
| 4 |
[](https://github.com/awesomized/crc-fast-rust/actions?query=workflow%3ATests) |
| 5 |
[](https://crates.io/crates/crc-fast) |
| 6 |
[](https://docs.rs/crc-fast) |
| 7 |
|
| 8 |
World's fastest generic CRC calculator for |
| 9 |
[all known CRC-16, CRC-32, and CRC-64 variants](https://reveng.sourceforge.io/crc-catalogue/all.htm), as well as bring-your-own |
| 10 |
custom parameters, using SIMD intrinsics, |
| 11 |
which can exceed [100GiB/s](#performance) on modern systems. |
| 12 |
|
| 13 |
Supports acceleration on `aarch64`, `x86_64`, and `x86` architectures, plus has a safe non-accelerated table-based |
| 14 |
software fallback for others. |
| 15 |
|
| 16 |
The [crc crate](https://crates.io/crates/crc) is ~0.5GiB/s by default, so this is |
| 17 |
[up to >220X faster](#tldr-just-tell-me-how-to-turn-it-up-to-11-). |
| 18 |
|
| 19 |
This is unique, not just because of the performance, but also because I couldn't find a single generic SIMD-accelerated |
| 20 |
implementation (in any language) which worked for _all_ known variants, using the |
| 21 |
[Rocksoft model](http://www.ross.net/crc/download/crc_v3.txt), especially the "non-reflected" variants. |
| 22 |
|
| 23 |
So I wrote one. :) |
| 24 |
|
| 25 |
## Other languages |
| 26 |
|
| 27 |
Supplies a [C/C++ compatible library](#cc-compatible-library) for use with other non-`Rust` languages. |
| 28 |
|
| 29 |
## Implementations |
| 30 |
|
| 31 |
* [AWS SDK for Rust](https://awslabs.github.io/aws-sdk-rust/) via |
| 32 |
the [aws-smithy-checksums](https://crates.io/crates/aws-smithy-checksums) crate. |
| 33 |
* [crc-fast-php-ext](https://github.com/awesomized/crc-fast-php-ext) `PHP` extension using this library. |
| 34 |
|
| 35 |
## Changes |
| 36 |
|
| 37 |
See [CHANGELOG](CHANGELOG.md). |
| 38 |
|
| 39 |
## Build & Install |
| 40 |
|
| 41 |
### Library |
| 42 |
|
| 43 |
`cargo build --release` will obviously build the Rust library, including |
| 44 |
the [C/C++ compatible dynamic and static libraries](#cc-compatible-library). |
| 45 |
|
| 46 |
### CLI tools |
| 47 |
|
| 48 |
There are some command-line tools available: |
| 49 |
|
| 50 |
- `checksum` calculates CRC checksums from the supplied string or file |
| 51 |
- `get-custom-params` generates the custom CRC parameters for the supplied Rocksoft model values |
| 52 |
- `arch-check` checks the current architecture's hardware acceleration features (primarily for debugging) |
| 53 |
|
| 54 |
To build them, enable the `cli` feature: `cargo build --features cli --release`. |
| 55 |
|
| 56 |
### Everything |
| 57 |
|
| 58 |
To build the libraries and the CLI tools, use the `--all-features` flag: `cargo build --all-features --release`. |
| 59 |
|
| 60 |
A _very_ basic [Makefile](Makefile) is supplied which supports `make install` to install the libraries, header file, and |
| 61 |
CLI binaries to the local system. Specifying the `DESTDIR` environment variable will allow you to customize the install |
| 62 |
location. |
| 63 |
|
| 64 |
``` |
| 65 |
DESTDIR=/my/custom/path make install |
| 66 |
``` |
| 67 |
|
| 68 |
## Features |
| 69 |
|
| 70 |
The library supports various feature flags for different environments: |
| 71 |
|
| 72 |
### Default Features |
| 73 |
* `std` - Standard library support, includes `alloc` |
| 74 |
* `ffi` - C/C++ FFI bindings for shared library (will become optional in v2.0) |
| 75 |
* `panic-handler` - Provides panic handler for `no_std` environments (disable when building binaries) |
| 76 |
|
| 77 |
### Optional Features |
| 78 |
* `alloc` - Heap allocation support (enables `Digest` trait, custom CRC params, checksum combining) |
| 79 |
* `cache` - Caches generated constants for custom CRC parameters (requires `alloc`) |
| 80 |
* `cli` - Enables command-line tools (`checksum`, `arch-check`, `get-custom-params`) |
| 81 |
|
| 82 |
### Building for `no_std` |
| 83 |
|
| 84 |
For embedded targets without standard library: |
| 85 |
|
| 86 |
```bash |
| 87 |
# Minimal no_std (core CRC only, no heap) |
| 88 |
cargo build --target thumbv7em-none-eabihf --no-default-features --lib |
| 89 |
|
| 90 |
# With heap allocation (enables Digest, custom params) |
| 91 |
cargo build --target thumbv7em-none-eabihf --no-default-features --features alloc --lib |
| 92 |
|
| 93 |
# With caching (requires alloc) |
| 94 |
cargo build --target thumbv7em-none-eabihf --no-default-features --features cache --lib |
| 95 |
``` |
| 96 |
|
| 97 |
Tested on ARM Cortex-M (`thumbv7em-none-eabihf`, `thumbv8m.main-none-eabihf`) and RISC-V ( |
| 98 |
`riscv32imac-unknown-none-elf`). |
| 99 |
|
| 100 |
### Building for `WASM` |
| 101 |
|
| 102 |
For WebAssembly targets: |
| 103 |
|
| 104 |
```bash |
| 105 |
# Minimal WASM |
| 106 |
cargo build --target wasm32-unknown-unknown --no-default-features --lib |
| 107 |
|
| 108 |
# With heap allocation (typical use case) |
| 109 |
cargo build --target wasm32-unknown-unknown --no-default-features --features alloc --lib |
| 110 |
|
| 111 |
# Using wasm-pack for browser |
| 112 |
wasm-pack build --target web --no-default-features --features alloc |
| 113 |
``` |
| 114 |
|
| 115 |
Tested on `wasm32-unknown-unknown`, `wasm32-wasip1`, and `wasm32-wasip2` targets. |
| 116 |
|
| 117 |
## Usage |
| 118 |
|
| 119 |
Add `crc-fast = "1"` to your `Cargo.toml` dependencies, which will enable every available optimization for |
| 120 |
the `stable` toolchain. |
| 121 |
|
| 122 |
### Fast helper functions |
| 123 |
|
| 124 |
For the [most common and popular](#important-crc-variants) CRC variants, there are specialized one-shot functions to make adoption easier and |
| 125 |
performance faster, particularly for smaller input sizes, since it reduces some of the overhead of the generic |
| 126 |
`checksum` path. |
| 127 |
|
| 128 |
#### CRC-32/ISCSI |
| 129 |
|
| 130 |
Also commonly known as `crc32c` in many, but not all, implementations. |
| 131 |
|
| 132 |
```rust |
| 133 |
use crc_fast::crc32_iscsi; |
| 134 |
|
| 135 |
let checksum = crc32_iscsi(b"123456789"); |
| 136 |
|
| 137 |
assert_eq!(checksum, 0xe3069283); |
| 138 |
``` |
| 139 |
|
| 140 |
#### CRC-32/ISO-HDLC |
| 141 |
|
| 142 |
Also commonly known as `crc32` in many, but not all, implementations. |
| 143 |
|
| 144 |
```rust |
| 145 |
use crc_fast::crc32_iso_hdlc; |
| 146 |
|
| 147 |
let checksum = crc32_iso_hdlc(b"123456789"); |
| 148 |
|
| 149 |
assert_eq!(checksum, 0xcbf43926); |
| 150 |
``` |
| 151 |
|
| 152 |
#### CRC-64/NVME |
| 153 |
|
| 154 |
```rust |
| 155 |
use crc_fast::crc64_nvme; |
| 156 |
|
| 157 |
let checksum = crc64_nvme(b"123456789"); |
| 158 |
|
| 159 |
assert_eq!(checksum, 0xae8b14860a799888); |
| 160 |
``` |
| 161 |
|
| 162 |
### Digest |
| 163 |
|
| 164 |
Implements the [digest::DynDigest](https://docs.rs/digest/latest/digest/trait.DynDigest.html) |
| 165 |
trait for easier integration with existing Rust code. |
| 166 |
|
| 167 |
Creates a `Digest` which can be updated over time, for stream processing, intermittent workloads, etc, enabling |
| 168 |
finalizing the checksum once processing is complete. |
| 169 |
|
| 170 |
```rust |
| 171 |
use crc_fast::{Digest, CrcAlgorithm::Crc32IsoHdlc}; |
| 172 |
|
| 173 |
let mut digest = Digest::new(Crc32IsoHdlc); |
| 174 |
digest.update(b"1234"); |
| 175 |
digest.update(b"56789"); |
| 176 |
let checksum = digest.finalize(); |
| 177 |
|
| 178 |
assert_eq!(checksum, 0xcbf43926); |
| 179 |
``` |
| 180 |
|
| 181 |
### Digest Write |
| 182 |
|
| 183 |
Implements the [std::io::Write](https://doc.rust-lang.org/std/io/trait.Write.html) trait for |
| 184 |
easier integration with existing Rust code. |
| 185 |
|
| 186 |
```rust |
| 187 |
use std::env; |
| 188 |
use std::fs::File; |
| 189 |
use crc_fast::{Digest, CrcAlgorithm::Crc32IsoHdlc}; |
| 190 |
|
| 191 |
// for example/test purposes only, use your own file path |
| 192 |
let binding = env::current_dir().expect("missing working dir").join("crc-check.txt"); |
| 193 |
let file_on_disk = binding.to_str().unwrap(); |
| 194 |
|
| 195 |
// actual usage |
| 196 |
let mut digest = Digest::new(Crc32IsoHdlc); |
| 197 |
let mut file = File::open(file_on_disk).unwrap(); |
| 198 |
std::io::copy( & mut file, & mut digest).unwrap(); |
| 199 |
let checksum = digest.finalize(); |
| 200 |
|
| 201 |
assert_eq!(checksum, 0xcbf43926); |
| 202 |
``` |
| 203 |
|
| 204 |
### checksum |
| 205 |
|
| 206 |
Checksums a string. |
| 207 |
|
| 208 |
```rust |
| 209 |
use crc_fast::{checksum, CrcAlgorithm::Crc32IsoHdlc}; |
| 210 |
|
| 211 |
let checksum = checksum(Crc32IsoHdlc, b"123456789"); |
| 212 |
|
| 213 |
assert_eq!(checksum, 0xcbf43926); |
| 214 |
``` |
| 215 |
|
| 216 |
### checksum_combine |
| 217 |
|
| 218 |
Combines checksums from two different sources, which can be useful for distributed or multithreaded workloads, etc. |
| 219 |
|
| 220 |
```rust |
| 221 |
use crc_fast::{checksum, checksum_combine, CrcAlgorithm::Crc32IsoHdlc}; |
| 222 |
|
| 223 |
let checksum_1 = checksum(Crc32IsoHdlc, b"1234"); |
| 224 |
let checksum_2 = checksum(Crc32IsoHdlc, b"56789"); |
| 225 |
let checksum = checksum_combine(Crc32IsoHdlc, checksum_1, checksum_2, 5); |
| 226 |
|
| 227 |
assert_eq!(checksum, 0xcbf43926); |
| 228 |
``` |
| 229 |
|
| 230 |
### checksum_file |
| 231 |
|
| 232 |
Checksums a file, which will chunk through the file optimally, limiting RAM usage and maximizing throughput. Chunk size |
| 233 |
is optional. |
| 234 |
|
| 235 |
```rust |
| 236 |
use crc_fast::{checksum_file, CrcAlgorithm::Crc32IsoHdlc}; |
| 237 |
|
| 238 |
// for example/test purposes only, use your own file path |
| 239 |
let binding = env::current_dir().expect("missing working dir").join("crc-check.txt"); |
| 240 |
let file_on_disk = binding.to_str().unwrap(); |
| 241 |
|
| 242 |
let checksum = checksum_file(Crc32IsoHdlc, file_on_disk, None); |
| 243 |
|
| 244 |
assert_eq!(checksum.unwrap(), 0xcbf43926); |
| 245 |
``` |
| 246 |
|
| 247 |
## Custom CRC Parameters |
| 248 |
|
| 249 |
For cases where you need to use CRC variants not included in the predefined algorithms, you can define custom CRC |
| 250 |
parameters and use the `*_with_params` functions. |
| 251 |
|
| 252 |
### Digest with custom parameters |
| 253 |
|
| 254 |
Creates a `Digest` with custom CRC parameters for stream processing. |
| 255 |
|
| 256 |
```rust |
| 257 |
use crc_fast::{Digest, CrcParams}; |
| 258 |
|
| 259 |
// Define custom CRC-32 parameters (equivalent to CRC-32/ISO-HDLC) |
| 260 |
let custom_params = CrcParams::new( |
| 261 |
"CRC-32/CUSTOM", |
| 262 |
32, |
| 263 |
0x04c11db7, |
| 264 |
0xffffffff, |
| 265 |
true, |
| 266 |
0xffffffff, |
| 267 |
0xcbf43926, |
| 268 |
); |
| 269 |
|
| 270 |
let mut digest = Digest::new_with_params(custom_params); |
| 271 |
digest.update(b"123456789"); |
| 272 |
let checksum = digest.finalize(); |
| 273 |
|
| 274 |
assert_eq!(checksum, 0xcbf43926); |
| 275 |
``` |
| 276 |
|
| 277 |
### checksum_with_params |
| 278 |
|
| 279 |
Checksums data using custom CRC parameters. |
| 280 |
|
| 281 |
```rust |
| 282 |
use crc_fast::{checksum_with_params, CrcParams}; |
| 283 |
|
| 284 |
// Define custom CRC-32 parameters (equivalent to CRC-32/ISO-HDLC) |
| 285 |
let custom_params = CrcParams::new( |
| 286 |
"CRC-32/CUSTOM", |
| 287 |
32, |
| 288 |
0x04c11db7, |
| 289 |
0xffffffff, |
| 290 |
true, |
| 291 |
0xffffffff, |
| 292 |
0xcbf43926, |
| 293 |
); |
| 294 |
|
| 295 |
let checksum = checksum_with_params(custom_params, b"123456789"); |
| 296 |
|
| 297 |
assert_eq!(checksum, 0xcbf43926); |
| 298 |
``` |
| 299 |
|
| 300 |
### checksum_combine_with_params |
| 301 |
|
| 302 |
Combines checksums from two different sources using custom CRC parameters. |
| 303 |
|
| 304 |
```rust |
| 305 |
use crc_fast::{checksum_with_params, checksum_combine_with_params, CrcParams}; |
| 306 |
|
| 307 |
// Define custom CRC-32 parameters (equivalent to CRC-32/ISO-HDLC) |
| 308 |
let custom_params = CrcParams::new( |
| 309 |
"CRC-32/CUSTOM", |
| 310 |
32, |
| 311 |
0x04c11db7, |
| 312 |
0xffffffff, |
| 313 |
true, |
| 314 |
0xffffffff, |
| 315 |
0xcbf43926, |
| 316 |
); |
| 317 |
|
| 318 |
let checksum_1 = checksum_with_params(custom_params, b"1234"); |
| 319 |
let checksum_2 = checksum_with_params(custom_params, b"56789"); |
| 320 |
let checksum = checksum_combine_with_params(custom_params, checksum_1, checksum_2, 5); |
| 321 |
|
| 322 |
assert_eq!(checksum, 0xcbf43926); |
| 323 |
``` |
| 324 |
|
| 325 |
### checksum_file_with_params |
| 326 |
|
| 327 |
Checksums a file using custom CRC parameters, chunking through the file optimally. |
| 328 |
|
| 329 |
```rust |
| 330 |
use std::env; |
| 331 |
use crc_fast::{checksum_file_with_params, CrcParams}; |
| 332 |
|
| 333 |
// for example/test purposes only, use your own file path |
| 334 |
let binding = env::current_dir().expect("missing working dir").join("crc-check.txt"); |
| 335 |
let file_on_disk = binding.to_str().unwrap(); |
| 336 |
|
| 337 |
// Define custom CRC-32 parameters (equivalent to CRC-32/ISO-HDLC) |
| 338 |
let custom_params = CrcParams::new( |
| 339 |
"CRC-32/CUSTOM", |
| 340 |
32, |
| 341 |
0x04c11db7, |
| 342 |
0xffffffff, |
| 343 |
true, |
| 344 |
0xffffffff, |
| 345 |
0xcbf43926, |
| 346 |
); |
| 347 |
|
| 348 |
let checksum = checksum_file_with_params(custom_params, file_on_disk, None); |
| 349 |
|
| 350 |
assert_eq!(checksum.unwrap(), 0xcbf43926); |
| 351 |
``` |
| 352 |
|
| 353 |
## C/C++ compatible library |
| 354 |
|
| 355 |
`cargo build` will produce a shared library target (`.so` on Linux, `.dll` on Windows, `.dylib` on macOS, etc) and an |
| 356 |
auto-generated [libcrc_fast.h](libcrc_fast.h) header file for use in non-Rust projects, such as through |
| 357 |
[FFI](https://en.wikipedia.org/wiki/Foreign_function_interface). It will also produce a static library target (`.a` on |
| 358 |
Linux and macOS, `.lib` on Windows, etc) for projects |
| 359 |
which prefer statically linking. |
| 360 |
|
| 361 |
There is a [crc-fast PHP extension](https://github.com/awesomized/crc-fast-php-ext) using it, for example. |
| 362 |
|
| 363 |
## Background |
| 364 |
|
| 365 |
This implementation is based on Intel's |
| 366 |
[Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction](https://web.archive.org/web/20131224125630/https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf) |
| 367 |
white paper, though it folds 8-at-a-time, like other modern implementations, rather than the 4-at-a-time as in Intel's |
| 368 |
paper. |
| 369 |
|
| 370 |
This library works on `aarch64`, `x86_64`, and `x86` architectures, and is hardware-accelerated and optimized for each |
| 371 |
architecture. |
| 372 |
|
| 373 |
Inspired by [`crc32fast`](https://crates.io/crates/crc32fast), |
| 374 |
[`crc64fast`](https://crates.io/crates/crc64fast), |
| 375 |
and [`crc64fast-nvme`](https://crates.io/crates/crc64fast-nvme), each of which only accelerates a single, different CRC |
| 376 |
variant, and all of them were "reflected" variants. |
| 377 |
|
| 378 |
In contrast, this library accelerates _every known variant_ (and should accelerate any future variants without changes), |
| 379 |
including all the "non-reflected" variants. |
| 380 |
|
| 381 |
## Important CRC variants |
| 382 |
|
| 383 |
While there are [many variants](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-32-iso-hdlc), three |
| 384 |
stand out as being the most important and widely used (all of which are "reflected"): |
| 385 |
|
| 386 |
### [CRC-32/ISCSI](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-32-iscsi) |
| 387 |
|
| 388 |
Many, but not all, implementations simply call this `crc32c` and it's probably the 2nd most popular and widely used, |
| 389 |
after `CRC-32/ISO-HDLC`. It's used in `iSCSI`, `ext4`, `btrfs`, etc. |
| 390 |
|
| 391 |
Both `x86_64` and `aarch64` have native hardware support for this CRC variant, so we can use |
| 392 |
[fusion](https://www.corsix.org/content/fast-crc32c-4k) in many cases to accelerate it further by fusing SIMD CLMUL |
| 393 |
instructions with the native CRC instructions. |
| 394 |
|
| 395 |
### [CRC-32/ISO-HDLC](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-32-iso-hdlc) |
| 396 |
|
| 397 |
Many, but not all, implementations simply call this `crc32` and it may be the most popular and widely used. It's used in |
| 398 |
`Ethernet`, `PKZIP`, `xz`, etc. |
| 399 |
|
| 400 |
Only `aarch64` has native hardware support for this CRC variant, so we can use |
| 401 |
[fusion](https://www.corsix.org/content/fast-crc32c-4k) on that platform, but not `x86_64`. |
| 402 |
|
| 403 |
### [CRC-64/NVME](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-64-nvme) |
| 404 |
|
| 405 |
`CRC-64/NVME` comes from |
| 406 |
the [NVM Express® NVM Command Set Specification](https://nvmexpress.org/wp-content/uploads/NVM-Express-NVM-Command-Set-Specification-1.0d-2023.12.28-Ratified.pdf) |
| 407 |
(Revision 1.0d, December 2023), |
| 408 |
is [AWS S3's recommended checksum option](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html) |
| 409 |
(as `CRC64-NVME`), and has also been implemented in the |
| 410 |
[Linux kernel](https://github.com/torvalds/linux/blob/786c8248dbd33a5a7a07f7c6e55a7bfc68d2ca48/lib/crc64.c#L66-L73) |
| 411 |
(where it's been called `CRC-64/Rocksoft` in the past). |
| 412 |
|
| 413 |
Note that the `Check` value in the `NVMe` spec uses incorrect endianness (see `Section 5.2.1.3.4, Figure 120, page 83`) |
| 414 |
but all known public & private implementations agree on the correct value, which this library produces. |
| 415 |
|
| 416 |
# Acceleration targets |
| 417 |
|
| 418 |
This library has baseline support for accelerating all known `CRC-16`, `CRC-32`, and `CRC-64` variants on `aarch64`, |
| 419 |
`x86_64`, and |
| 420 |
`x86` internally in pure `Rust`. |
| 421 |
|
| 422 |
It uses the best available acceleration method for the detected CPU features at runtime, including: |
| 423 |
* `aarch64`: |
| 424 |
* `neon-pmull-sha3` (preferred, if available) |
| 425 |
* `neon-pmull` |
| 426 |
* `x86_64` and `x86`: |
| 427 |
* `avx512-vpclmulqdq` (preferred, if available) |
| 428 |
* `avx512-pclmulqdq` |
| 429 |
* `sse-pclmulqdq` |
| 430 |
|
| 431 |
There is a safe table-based software fallback for other architectures, or if no acceleration features are detected. |
| 432 |
|
| 433 |
### Checking your platform capabilities |
| 434 |
|
| 435 |
There's an [arch-check](src/bin/arch-check.rs) binary which will explain the selected target architecture. |
| 436 |
|
| 437 |
``` |
| 438 |
// test it works on your system (patches welcome!) |
| 439 |
cargo test |
| 440 |
|
| 441 |
// examine the chosen acceleration targets |
| 442 |
cargo run arch-check |
| 443 |
|
| 444 |
// build for release |
| 445 |
cargo build --release |
| 446 |
``` |
| 447 |
|
| 448 |
## Minimum Supported Rust Version (MSRV) |
| 449 |
|
| 450 |
This crate targets a `stable-2` policy (ie, the latest stable Rust version minus 2 minor versions) as the Minimum |
| 451 |
Supported Rust Version (MSRV). |
| 452 |
|
| 453 |
Bumping the `rust-version` will be considered a **MINOR** version bump. |
| 454 |
|
| 455 |
We'll try to support even older versions when possible, but given the high-performance use of SIMD intrinsics and other |
| 456 |
modern Rust features, this is merely a stated goal. We'll move up to `stable-2` ASAP when a sufficiently high |
| 457 |
performance improvement or necessary feature requires it. |
| 458 |
|
| 459 |
## Performance |
| 460 |
|
| 461 |
Modern systems can exceed 100 GiB/s for calculating `CRC-32/ISCSI`, and nearly 90 GiB/s for `CRC-32/ISO-HDLC`, |
| 462 |
`CRC-64/NVME`, and all other reflected variants. (Forward variants are slower, due to the extra shuffle-masking, but |
| 463 |
are still extremely fast in this library). |
| 464 |
|
| 465 |
This is a summary of the performance for the most important and popular CRC checksums. |
| 466 |
|
| 467 |
### CRC-32/ISCSI (reflected) |
| 468 |
|
| 469 |
AKA `crc32c` in many, but not all, implementations. |
| 470 |
|
| 471 |
|
| 472 |
|
| 473 |
| x86_64 | Intel | Sapphire Rapids | EC2 c7i.metal-24xl | avx512-vpclmulqdq | ~61 | ~111 | |
| 474 |
| x86_64 | AMD | Genoa | EC2 c7a.metal-48xl | avx512-vpclmulqdq | ~26 | ~54 | |
| 475 |
| aarch64 | AWS | Graviton4 | EC2 c8g.metal-48xl | neon-pmull-sha3 | ~23 | ~54 | |
| 476 |
| aarch64 | AWS | Graviton2 | EC2 c6g.metal | neon-pmull | ~11 | ~17 | |
| 477 |
| aarch64 | Apple | M3 Ultra | Mac Studio (32 core) | neon-pmull-sha3 | ~60 | ~99 | |
| 478 |
| aarch64 | Apple | M4 Max | MacBook Pro 16" (16 core) | neon-pmull-sha3 | ~56 | ~94 | |
| 479 |
|
| 480 |
### CRC-32/ISO-HDLC (reflected) |
| 481 |
|
| 482 |
AKA `crc32` in many, but not all, implementations. |
| 483 |
|
| 484 |
|
| 485 |
|
| 486 |
| x86_64 | Intel | Sapphire Rapids | EC2 c7i.metal-248xl | avx512-vpclmulqdq | ~28 | ~88 | |
| 487 |
| x86_64 | AMD | Genoa | EC2 c7a.metal-48xl | avx512-vpclmulqdq | ~21 | ~55 | |
| 488 |
| aarch64 | AWS | Graviton4 | EC2 c8g.metal-48xl | neon-pmull-sha3 | ~23 | ~54 | |
| 489 |
| aarch64 | AWS | Graviton2 | EC2 c6g.metal | neon-pmull | ~11 | ~17 | |
| 490 |
| aarch64 | Apple | M3 Ultra | Mac Studio (32 core) | neon-pmull-sha3 | ~48 | ~98 | |
| 491 |
| aarch64 | Apple | M4 Max | MacBook Pro 16" (16 core) | neon-pmull-sha3 | ~56 | ~94 | |
| 492 |
|
| 493 |
### CRC-64/NVME (reflected) |
| 494 |
|
| 495 |
[AWS S3's recommended checksum option](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html) |
| 496 |
|
| 497 |
|
| 498 |
|
| 499 |
| x86_64 | Intel | Sapphire Rapids | EC2 c7i.metal-24xl | avx512-vpclmulqdq | ~28 | ~88 | |
| 500 |
| x86_64 | AMD | Genoa | EC2 c7a.metal-48xl | avx512-vpclmulqdq | ~22 | ~55 | |
| 501 |
| aarch64 | AWS | Graviton4 | EC2 c8g.metal-48xl | neon-pmull-sha3 | ~28 | ~41 | |
| 502 |
| aarch64 | AWS | Graviton2 | EC2 c6g.metal | neon-pmull | ~11 | ~16 | |
| 503 |
| aarch64 | Apple | M3 Ultra | Mac Studio (32 core) | neon-pmull-sha3 | ~58 | ~72 | |
| 504 |
| aarch64 | Apple | M4 Max | MacBook Pro 16" (16 core) | neon-pmull-sha3 | ~52 | ~72 | |
| 505 |
|
| 506 |
### CRC-32/BZIP2 (forward) |
| 507 |
|
| 508 |
|
| 509 |
|
| 510 |
| x86_64 | Intel | Sapphire Rapids | EC2 c7i.metal-24xl | avx512-vpclmulqdq | ~20 | ~56 | |
| 511 |
| x86_64 | AMD | Genoa | EC2 c7a.metal-48xl | avx512-vpclmulqdq | ~14 | ~43 | |
| 512 |
| aarch64 | AWS | Graviton4 | EC2 c8g.metal-48xl | neon-pmull-eor3 | ~18 | ~40 | |
| 513 |
| aarch64 | AWS | Graviton2 | EC2 c6g.metal | neon-pmull | ~9 | ~14 | |
| 514 |
| aarch64 | Apple | M3 Ultra | Mac Studio (32 core) | neon-pmull-eor3 | ~41 | ~59 | |
| 515 |
| aarch64 | Apple | M4 Max | MacBook Pro 16" (16 core) | neon-pmull-eor3 | ~47 | ~64 | |
| 516 |
|
| 517 |
### CRC-64/ECMA-182 (forward) |
| 518 |
|
| 519 |
|
| 520 |
|
| 521 |
| x86_64 | Intel | Sapphire Rapids | EC2 c7i.metal-24xl | avx512-vpclmulqdq | ~21 | ~56 | |
| 522 |
| x86_64 | AMD | Genoa | EC2 c7a.metal-48xl | avx512-vpclmulqdq | ~14 | ~43 | |
| 523 |
| aarch64 | AWS | Graviton4 | EC2 c8g.metal-48xl | neon-pmull-eor3 | ~19 | ~40 | |
| 524 |
| aarch64 | AWS | Graviton2 | EC2 c6g.metal | neon-pmull | ~9 | ~14 | |
| 525 |
| aarch64 | Apple | M3 Ultra | Mac Studio (32 core) | neon-pmull-eor3 | ~40 | ~59 | |
| 526 |
| aarch64 | Apple | M4 Max | MacBook Pro 16" (16 core) | neon-pmull-eor3 | ~46 | ~61 | |
| 527 |
|
| 528 |
## Other CRC widths |
| 529 |
|
| 530 |
There are [a lot of other known CRC widths and variants](https://reveng.sourceforge.io/crc-catalogue/all.htm), ranging |
| 531 |
from `CRC-3/GSM` to `CRC-82/DARC`, and everything in between. |
| 532 |
|
| 533 |
Since [Awesome](https://awesome.co) only uses `CRC-32` or `CRC-64` widths in our products, this library began by supporting only those |
| 534 |
widths, including all known variants plus support for custom [Rocksoft](http://www.ross.net/crc/download/crc_v3.txt) |
| 535 |
parameters. |
| 536 |
|
| 537 |
`CRC-16` has since been added, including all known variants plus support for custom parameters as well. |
| 538 |
|
| 539 |
In theory, much of the "heavy lifting" has been done, so it should be possible to add other widths with minimal effort. |
| 540 |
|
| 541 |
PRs welcome! |
| 542 |
|
| 543 |
## Memory Safety |
| 544 |
|
| 545 |
Given the heavy use of hardware intrinsics, this crate uses a decent amount of `unsafe` code. |
| 546 |
|
| 547 |
To help ensure memory safety and stability, this crate is validated using [Miri](https://github.com/rust-lang/miri) on |
| 548 |
`x86_64` as well as fuzz tested using [libFuzzer](https://github.com/rust-fuzz/libfuzzer) over millions of iterations. |
| 549 |
|
| 550 |
## References |
| 551 |
|
| 552 |
* [Catalogue of parametrised CRC algorithms](https://reveng.sourceforge.io/crc-catalogue/all.htm) |
| 553 |
* [crc32-fast](https://crates.io/crates/crc32fast) Original `CRC-32/ISO-HDLC` (`crc32`) implementation in `Rust`. |
| 554 |
* [crc64-fast](https://github.com/tikv/crc64fast) Original `CRC-64/XZ` implementation in `Rust`. |
| 555 |
* [crc64fast-nvme](https://github.com/awesomized/crc64fast-nvme) Original `CRC-64/NVME` implementation in `Rust`. |
| 556 |
* [Fast CRC Computation for Generic Polynomials Using PCLMULQDQ Instruction](https://web.archive.org/web/20131224125630/https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/fast-crc-computation-generic-polynomials-pclmulqdq-paper.pdf) |
| 557 |
Intel's paper. |
| 558 |
* [NVM Express® NVM Command Set Specification](https://nvmexpress.org/wp-content/uploads/NVM-Express-NVM-Command-Set-Specification-1.0d-2023.12.28-Ratified.pdf) |
| 559 |
The NVMe spec, including `CRC-64-NVME` (with incorrect endian `Check` value in |
| 560 |
`Section 5.2.1.3.4, Figure 120, page 83`). |
| 561 |
* [CRC-64/NVME](https://reveng.sourceforge.io/crc-catalogue/all.htm#crc.cat.crc-64-nvme) The `CRC-64/NVME` quick |
| 562 |
definition. |
| 563 |
* [A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS](http://www.ross.net/crc/download/crc_v3.txt) Best description of |
| 564 |
CRC I've seen to date (and the definition of the Rocksoft model). |
| 565 |
* [Linux implementation](https://github.com/torvalds/linux/blob/786c8248dbd33a5a7a07f7c6e55a7bfc68d2ca48/lib/crc64.c) |
| 566 |
Linux implementation of `CRC-64/NVME`. |
| 567 |
* [MASM/C++ artifacts implementation](https://github.com/jeffareid/crc/) - Reference MASM/C++ implementation for |
| 568 |
generating artifacts. |
| 569 |
* [Intel isa-l GH issue #88](https://github.com/intel/isa-l/issues/88) - Additional insight into generating artifacts. |
| 570 |
* [StackOverflow PCLMULQDQ CRC32 answer](https://stackoverflow.com/questions/71328336/fast-crc-with-pclmulqdq-not-reflected/71329114#71329114) |
| 571 |
Insightful answer to implementation details for CRC32. |
| 572 |
* [StackOverflow PCLMULQDQ CRC32 question](https://stackoverflow.com/questions/21171733/calculating-constants-for-crc32-using-pclmulqdq) |
| 573 |
Insightful question & answer to CRC32 implementation details. |
| 574 |
* [AWS S3 announcement about CRC64-NVME support](https://aws.amazon.com/blogs/aws/introducing-default-data-integrity-protections-for-new-objects-in-amazon-s3/) |
| 575 |
* [AWS S3 docs on checking object integrity using CRC64-NVME](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html) |
| 576 |
* [Vector Carry-Less Multiplication of Quadwords (VPCLMULQDQ) details](https://en.wikichip.org/wiki/x86/vpclmulqdq) |
| 577 |
* [Linux kernel updates by Eric Biggers to use VPCLMULQDQ, etc](https://lkml.org/lkml/2025/2/10/1367) |
| 578 |
* [Faster CRC32-C on x86](https://www.corsix.org/content/fast-crc32c-4k) |
| 579 |
* [Faster CRC32 on the Apple M1](https://dougallj.wordpress.com/2022/05/22/faster-crc32-on-the-apple-m1/) |
| 580 |
* [An alternative exposition of crc32_4k_pclmulqdq](https://www.corsix.org/content/alternative-exposition-crc32_4k_pclmulqdq) |
| 581 |
* [fast-crc32](https://github.com/corsix/fast-crc32) - implementations of fusion for two CRC-32 variants. |
| 582 |
|
| 583 |
## License |
| 584 |
|
| 585 |
`cfc-fast` is dual-licensed under |
| 586 |
|
| 587 |
* Apache 2.0 license ([LICENSE-Apache](./LICENSE-Apache) or <http://www.apache.org/licenses/LICENSE-2.0>) |
| 588 |
* MIT license ([LICENSE-MIT](./LICENSE-MIT) or <https://opensource.org/licenses/MIT>) |