SimpleHash
A simple Rust implementation of common non-cryptographic hash functions that are compatible with Rust's standard collections.
Currently Implemented
- FNV-1 (32-bit and 64-bit)
- FNV-1a (32-bit and 64-bit)
- MurmurHash3 (32-bit, 64-bit, and 128-bit)
- CityHash (64-bit)
- Rendezvous hashing (HRW - Highest Random Weight) algorithm
These hash functions (except for MurmurHash3 128-bit) implement the std::hash::Hasher trait, making them usable with HashMap and HashSet as faster alternatives to the default SipHash. The Rendezvous hashing implementation works with any hasher implementing the std::hash::Hasher trait.
Usage
Basic Usage
use ;
Using with HashMap and HashSet
You can use these hashers with Rust's standard collections for better performance:
use Fnv1aHasher64;
use MurmurHasher32;
use ;
use ;
// Using FNV-1a with HashMap
let mut map: =
with_hasher;
map.insert;
// Using FNV-1a with HashSet
let mut set: =
with_hasher;
set.insert;
// For MurmurHash3, create a BuildHasher implementation
;
// Using MurmurHash3 with HashMap
let mut murmur_map: =
with_hasher;
murmur_map.insert;
Using Rendezvous Hashing
Rendezvous hashing (also known as Highest Random Weight or HRW hashing) provides a way to consistently distribute data across a changing set of servers or nodes. This implementation is particularly useful for distributed systems that need minimal redistribution when nodes are added or removed.
use RendezvousHasher;
use RandomState;
use BuildHasherDefault;
use Fnv1aHasher64;
// Create a RendezvousHasher with the standard hasher
let std_hasher = new;
// Create a RendezvousHasher with FNV-1a 64-bit hasher (for better performance)
let fnv_hasher = new;
// Define a list of servers or nodes
let nodes = vec!;
// Find the preferred node for a key
let key = "user_profile_12345";
let selected_node = fnv_hasher.select.unwrap;
println!;
// Get all nodes ranked by preference for this key
let ranked_nodes = fnv_hasher.rank;
println!;
for in ranked_nodes.iter.enumerate
// The beauty of rendezvous hashing is that when a node is removed,
// only keys that were assigned to that specific node are redistributed
let reduced_nodes = vec!; // server3 removed
let new_node = fnv_hasher.select.unwrap;
When to Use Alternative Hashers
- For performance-critical code: When dealing with a large number of hash operations or collections with many elements
- For small keys: FNV performs exceptionally well with small keys, such as integers or short strings
- For medium to large inputs: MurmurHash3 offers better performance for larger inputs
- For string keys: CityHash was specifically designed by Google for string hashing and performs very well for string keys in hash tables (based on the original implementation by Geoff Pike and Jyrki Alakuijala)
- For internal/trusted data only: These hash functions lack the DoS protection of SipHash (Rust's default)
- For distributed systems: Rendezvous hashing is ideal for distributing data across multiple servers or nodes with minimal redistribution when the node set changes
Based on benchmarks, these hashers can provide significant performance improvements:
- FNV-1a is generally 1.5-2x faster than SipHash for small keys
- MurmurHash3 shows better performance for larger keys and provides better collision resistance
- CityHash performs exceptionally well for string keys, often outperforming other algorithms for common string lengths
- Rendezvous hashing with FNV-1a or MurmurHash3 provides excellent distribution properties while maintaining consistency when nodes are added or removed
Command Line Usage
# Build the project
# Run the CLI
Verification
This project includes verification scripts to ensure the hash implementations match reference implementations:
FNV Verification
# Generate the FNV test corpus using Go
# Verify FNV implementations against Go's reference implementation
MurmurHash3 Verification
# Generate the MurmurHash3 test corpus
# Run the verification tests
Benchmarks
SimpleHash includes benchmarks using the Criterion.rs library. To run the benchmarks:
# Run all benchmarks
# Run only FNV benchmarks
# Run comparative hash benchmarks
# Run HashMap/HashSet performance benchmarks
# Run Rendezvous hashing benchmarks
The benchmarks compare:
- FNV hashing implementations (FNV-1 and FNV-1a, 32-bit and 64-bit variants)
- MurmurHash3 implementations (32-bit, 64-bit, and 128-bit)
- Performance across various input sizes
- Different input patterns (zeros, ones, alternating, incremental)
- Realistic data inputs (strings, URLs, JSON, UUIDs)
- HashMap and HashSet performance with different hashers (SipHash vs FNV vs MurmurHash3)
- Collision resistance evaluation with similar keys
- Rendezvous hashing performance with different underlying hash functions and node counts
License
MIT