xxhash-rust

repository·master·Indexed 43 days ago

https://github.com/doumanash/xxhash-rust

A high-performance Rust implementation of the xxHash hashing algorithms, providing 32-bit, 64-bit, and xxh3 families. Version 0.8.18 supports SIMD hardware acceleration (SSE2, AVX2, AVX512, Neon, Wasm SIMD128) and compile-time constant hashing via `const fn`. It offers both optimized one-shot functions for complete buffers and streaming implementations for data processed in chunks.

Tokens
4.5K
Snippets
16
Records
23
Agent score
53%

What's inside xxhash-rust

  1. When to use one-shot vs streaming vs const fn

    master

    One-shot vs Streaming

    For performance reasons, the one-shot versions of the algorithms do not reuse the streaming implementation. Unless your specific use case requires streaming (e.g., hashing data in chunks), use the one-shot version for better performance.

    const fn usage

    const fn allows for compile-time hashing, but it is slower than the runtime implementation due to the limitations of Rust's const environment.

    Important: To ensure the hash is actually computed at compile time and not at runtime, you must initialize the output as a const or static variable. If you call a const fn within a regular function without assigning it to a const/static context, it will execute at runtime, which is less efficient than the standard algorithm.

  2. How hardware acceleration works in xxhash-rust

    master

    The xxh3 implementation includes SIMD accelerations. These checks are performed at compile time. To ensure your build uses the best available hardware acceleration for your target, it is recommended to use compiler flags like -C target-cpu=native.

    Supported SIMD accelerations:

    • SSE2: Widely available; enabled by default on x86_64 targets.
    • AVX2
    • AVX512
    • Neon: Enabled by default on most aarch64 targets.
    • Wasm SIMD128: Must be enabled via the Rust flag -Ctarget-feature=+simd128.
  3. Install xxhash-rust via Cargo

    master

    Add xxhash-rust to your Cargo.toml. Note that all algorithm features are off by default. You must explicitly enable the algorithms you intend to use (e.g., xxh3, xxh64) to control code size and include the necessary implementations.

    [dependencies.xxhash-rust]
    version = "0.8.12"
    features = ["xxh3", "const_xxh3"]
  4. Use `const fn` versions for compile-time hashing

    master

    The const_xxh* modules provide const fn implementations. These allow you to compute hashes at compile time.

    Important Usage Notes:

    • Performance: const fn implementations are slower than runtime versions due to Rust's const limitations. Only use them if you actually intend to compute the hash at compile time.
    • Guaranteeing Compile-Time Execution: To ensure the hash is computed at compile time and not at runtime, you must initialize the result as a const or static variable. If you assign the result of a const fn to a regular variable, it may be executed at runtime, which is less efficient than the standard runtime algorithm.
    use xxhash_rust::const_xxh3::xxh3_64 as const_xxh3;
    
    // This is computed at compile time
    const TEST: u64 = const_xxh3(b"TEST");
    
    fn main() {
        assert_eq!(TEST, const_xxh3(b"TEST"));
    }
  5. Use Xxh3Default for hash maps

    master

    If you are using XXH3 as a hasher for a HashMap or other collections that require the BuildHasher trait, use Xxh3Default. It is an optimized version of the streaming algorithm that uses the default seed and secret, making it ideal for the frequent creation/destruction cycle of hash map hasher instances.

    You can create it using Xxh3DefaultBuilder or by calling Xxh3Default::default().

    use xxhash_rust::xxh3::{Xxh3Default, Xxh3DefaultBuilder};
    use std::collections::HashMap;
    
    // Using the builder
    let hasher_builder = Xxh3DefaultBuilder::new().build();
    let mut map: HashMap<String, i32, Xxh3Default> = HashMap::with_hasher(hasher_builder);
    
    // Or using default directly
    let mut map: HashMap<String, i32, Xxh3Default> = HashMap::default();
  6. Use one-shot vs streaming hashing

    master

    The crate provides both one-shot and streaming versions of the algorithms.

    Recommendation: Unless you specifically need to process data in chunks, use the one-shot version. One-shot implementations are optimized for performance and do not reuse the streaming logic, making them generally more efficient for complete data buffers.

  7. Enable Hardware Acceleration (SIMD)

    master

    The xxh3 implementation uses SIMD acceleration (SSE2, AVX2, AVX512, Neon, Wasm SIMD128) depending on your target architecture. All SIMD checks are performed at compile time.

    To ensure the best performance, it is highly recommended to compile your project with target-specific optimizations, such as:

    rustc -C target-cpu=native

    SIMD Support Details:

    • SSE2: Widely available; enabled by default on x86_64 targets.
    • AVX2 / AVX512: Available on supported x86 hardware.
    • Neon: Enabled by default on aarch64 targets.
    • Wasm SIMD128: Must be explicitly enabled via the Rust flag: -C target-feature=+simd128.
  8. Use xxhash-rust algorithms

    master

    The crate provides both standard one-shot functions and const fn versions for compile-time computation. For general runtime use, use the one-shot versions as they are more optimized than the streaming or const fn alternatives.

    use xxhash_rust::const_xxh3::xxh3_64 as const_xxh3;
    use xxhash_rust::xxh3::xxh3_64;
    
    // Compute hash at compile time
    const TEST: u64 = const_xxh3(b"TEST");
    
    fn test_input(text: &str) -> bool {
        // Compute hash at runtime
        xxh3_64(text.as_bytes()) == TEST
    }
    
    assert!(!test_input("tEST"));
    assert!(test_input("TEST"));
  9. Reference available features

    master

    Each algorithm is implemented via a feature. By default, all features are disabled. Enable them as needed:

    • std - Enables std::io::Write trait implementation
    • xxh32 - Enables 32bit algorithm. Suitable for x86 targets
    • const_xxh32 - const fn version of xxh32 algorithm
    • xxh64 - Enables 64 algorithm. Suitable for x86_64 targets
    • const_xxh64 - const fn version of xxh64 algorithm
    • xxh3 - Enables xxh3 family of algorithms (superior performance)
    • const_xxh3 - const fn version of xxh3 algorithm
  10. Configure Xxh3 using Xxh3Builder

    master

    Use Xxh3Builder to construct a custom Xxh3 hasher using a fluent API. This is useful when you want to optionally set a seed or a secret.

    • with_seed(seed: u64): Sets the seed. This overrides the default secret with one derived from the seed.
    • with_secret(secret: [u8; DEFAULT_SECRET_SIZE]): Sets a custom secret. This takes precedence over the seed.
    • build(): Returns the constructed Xxh3 instance.
    use xxhash_rust::xxh3::Xxh3Builder;
    
    let secret = [0u8; 192]; // Example secret size
    let hasher = Xxh3Builder::new()
        .with_seed(12345)
        .with_secret(secret)
        .build();
  11. Use Xxh3 for streaming hashes with custom seeds or secrets

    master

    The Xxh3 struct provides a full streaming implementation of the XXH3 algorithm. Unlike Xxh3Default, it allows you to provide a custom seed or a custom secret (a byte array of DEFAULT_SECRET_SIZE).

    Note: Xxh3 maintains large internal buffers. If you are concerned about stack space, consider storing the Xxh3 instance on the heap.

    Key methods:

    • new(): Creates a hasher with default settings.
    • with_seed(seed: u64): Creates a hasher with a custom seed (which derives a secret).
    • with_secret(secret: [u8; DEFAULT_SECRET_SIZE]): Creates a hasher with a specific secret.
    • update(&mut self, input: &[u8]): Feeds data into the hasher.
    • digest(&self) -> u64: Computes the 64-bit hash.
    • digest128(&self) -> u128: Computes the 128-bit hash.
    • reset(&mut self): Resets the internal state for reuse.
    use xxhash_rust::xxh3::Xxh3;
    
    let mut hasher = Xxh3::with_seed(42);
    hasher.update(b"hello");
    hasher.update(b" world");
    let hash = hasher.digest();
    let hash128 = hasher.digest128();
  12. Reset an Xxh32 hasher

    master

    To reuse an existing Xxh32 instance without reallocating, use the reset method. This clears the internal buffer, resets the total length to zero, and re-initializes the internal state with the provided seed.

    let mut hasher = Xxh32::new(42);
    // ... use hasher ...
    // Reset to start a new hash with a different seed
    hasher.reset(123);