crc32fast

repository·master·Indexed 43 days ago

https://github.com/srijs/rust-crc32fast

A high-performance, SIMD-accelerated implementation of the CRC32 (IEEE) checksum algorithm in Rust. Version 1.5.2 provides a convenience `hash()` function for byte slices and a `Hasher` struct for incremental checksumming and state combination. It features automatic runtime CPU detection to utilize SSE, PCLMULQDQ, AVX2, AVX512, and AArch64 optimizations.

Tokens
1.4K
Snippets
6
Records
9
Agent score
56%

What's inside crc32fast

  1. Understand `crc32fast` performance and SIMD acceleration

    master

    The crate automatically selects the most optimal CRC32 implementation for your CPU at runtime when calling Hasher::new(). Supported accelerations include:

    • Baseline: A fast implementation processing up to 16 bytes per iteration.
    • x86 (SSE/PCLMULQDQ): Optimized using sse and pclmulqdq instructions.
    • x86 (AVX2/AVX512): Wider implementations using vpclmulqdq on 256-bit (avx2) and 512-bit (avx512f) registers (requires Rust 1.89+).
    • AArch64: Optimized using crc32 instructions, including a 3-way interleaved variant to hide instruction latency on large inputs.
  2. Set up fuzz testing for crc32fast

    master

    To perform fuzz testing on the crc32fast crate, you must have cargo-fuzz installed and use a nightly Rust toolchain. This allows for automated testing of the hasher target to identify potential edge cases or bugs.

    Follow these steps:

    1. Install the cargo-fuzz tool.
    2. Execute the hasher fuzzing target using a nightly toolchain.
    # 1. Install cargo-fuzz
    cargo install cargo-fuzz
    
    # 2. Run the hasher target
    cargo +nightly fuzz run hasher
  3. Configure `crc32fast` feature flags

    master

    The crate provides feature flags to control its dependencies and capabilities:

    • std (default: enabled): Enables support for the Rust standard library.
      • Note: Disabling std (for no_std environments like embedded systems) will make specialized SIMD implementations unavailable because runtime CPU feature detection requires OS support.
    • nightly (default: disabled): Enables unstable features available only on the Rust nightly channel. Enabling this may lead to breaking changes when updating compiler versions.
  4. How `Hasher` performance and CPU detection works

    master

    The Hasher automatically selects the most efficient implementation for your CPU at runtime when Hasher::new() is called. Supported implementations include:

    • Baseline: A fast fallback processing up to 16 bytes per iteration.
    • x86 (SSE/PCLMULQDQ): Optimized for modern x86 processors.
    • x86 (AVX2/AVX512): Wider implementations using vpclmulqdq on 256-bit or 512-bit registers (requires Rust 1.89+).
    • AArch64: Optimized using ARM crc32 instructions.
  5. Compute a CRC32 checksum with `hash()`

    master

    For simple use-cases where you only need to compute a checksum for a single byte slice, use the crc32fast::hash convenience function. This is the most direct way to get a checksum without managing state.

    let checksum = crc32fast::hash(b"foo bar baz");
  6. Compute CRC32 checksums with `Hasher`

    master

    For advanced use-cases, such as processing large amounts of data in chunks or requiring more flexibility, use the Hasher struct. This allows you to incrementally update the state before finalizing the checksum.

    use crc32fast::Hasher;
    
    let mut hasher = Hasher::new();
    hasher.update(b"foo bar baz");
    let checksum = hasher.finalize();
  7. Use `Hasher` for incremental checksumming

    master

    For more flexibility or performance—such as processing large amounts of data in chunks—use the Hasher struct. This allows you to update the hash state incrementally.

    use crc32fast::Hasher;
    
    let mut hasher = Hasher::new();
    hasher.update(b"foo bar baz");
    let checksum = hasher.finalize();
  8. Combine two `Hasher` states with `combine()`

    master

    The combine method allows you to merge the state of another Hasher into the current one. This is particularly useful for parallel processing or combining results from different data blocks without re-processing the original bytes. It effectively computes the CRC of the concatenated data: crc(current_data || other_data).

    Note that combine requires the other hasher to have its amount (length) correctly set, which is handled automatically when using standard update() calls on the other hasher.

    use crc32fast::Hasher;
    
    let mut hasher_a = Hasher::new();
    hasher_a.update(b"foo ");
    
    let mut hasher_b = Hasher::new();
    hasher_b.update(b"bar");
    
    // Combine b into a
    hasher_a.combine(&hasher_b);
    let checksum = hasher_a.finalize(); // Equivalent to crc(b"foo bar")
  9. Initialize a `Hasher` with custom state or length

    master

    The Hasher provides several ways to initialize its state:

    • new(): Creates a new hasher with the default initial state (0). Performs runtime CPU feature detection to select the optimal implementation.
    • new_with_initial(init: u32): Creates a new hasher starting with a specific initial CRC32 state.
    • new_with_initial_len(init: u32, amount: u64): Creates a new hasher with an initial state and a known byte length. This is useful when using combine to compute crc(a || b) from crc(a), crc(b), and len(b).
    use crc32fast::Hasher;
    
    // Default
    let mut hasher = Hasher::new();
    
    // With initial state
    let mut hasher = Hasher::new_with_initial(0x12345678);
    
    // With initial state and known length
    let mut hasher = Hasher::new_with_initial_len(0, 1024);