Joel Galenson | 513da8f | 2020-10-23 08:05:11 -0700 | [diff] [blame] | 1 | # rust-fnv |
| 2 | |
| 3 | An implementation of the [Fowler–Noll–Vo hash function][chongo]. |
| 4 | |
| 5 | ### [Read the documentation](https://doc.servo.org/fnv/) |
| 6 | |
| 7 | |
| 8 | ## About |
| 9 | |
| 10 | The FNV hash function is a custom `Hasher` implementation that is more |
| 11 | efficient for smaller hash keys. |
| 12 | |
| 13 | [The Rust FAQ states that][faq] while the default `Hasher` implementation, |
| 14 | SipHash, is good in many cases, it is notably slower than other algorithms |
| 15 | with short keys, such as when you have a map of integers to other values. |
| 16 | In cases like these, [FNV is demonstrably faster][graphs]. |
| 17 | |
| 18 | Its disadvantages are that it performs badly on larger inputs, and |
| 19 | provides no protection against collision attacks, where a malicious user |
| 20 | can craft specific keys designed to slow a hasher down. Thus, it is |
| 21 | important to profile your program to ensure that you are using small hash |
| 22 | keys, and be certain that your program could not be exposed to malicious |
| 23 | inputs (including being a networked server). |
| 24 | |
| 25 | The Rust compiler itself uses FNV, as it is not worried about |
| 26 | denial-of-service attacks, and can assume that its inputs are going to be |
| 27 | small—a perfect use case for FNV. |
| 28 | |
| 29 | |
| 30 | ## Usage |
| 31 | |
| 32 | To include this crate in your program, add the following to your `Cargo.toml`: |
| 33 | |
| 34 | ```toml |
| 35 | [dependencies] |
| 36 | fnv = "1.0.3" |
| 37 | ``` |
| 38 | |
| 39 | |
| 40 | ## Using FNV in a HashMap |
| 41 | |
| 42 | The `FnvHashMap` type alias is the easiest way to use the standard library’s |
| 43 | `HashMap` with FNV. |
| 44 | |
| 45 | ```rust |
| 46 | use fnv::FnvHashMap; |
| 47 | |
| 48 | let mut map = FnvHashMap::default(); |
| 49 | map.insert(1, "one"); |
| 50 | map.insert(2, "two"); |
| 51 | |
| 52 | map = FnvHashMap::with_capacity_and_hasher(10, Default::default()); |
| 53 | map.insert(1, "one"); |
| 54 | map.insert(2, "two"); |
| 55 | ``` |
| 56 | |
| 57 | Note, the standard library’s `HashMap::new` and `HashMap::with_capacity` |
| 58 | are only implemented for the `RandomState` hasher, so using `Default` to |
| 59 | get the hasher is the next best option. |
| 60 | |
| 61 | |
| 62 | ## Using FNV in a HashSet |
| 63 | |
| 64 | Similarly, `FnvHashSet` is a type alias for the standard library’s `HashSet` |
| 65 | with FNV. |
| 66 | |
| 67 | ```rust |
| 68 | use fnv::FnvHashSet; |
| 69 | |
| 70 | let mut set = FnvHashSet::default(); |
| 71 | set.insert(1); |
| 72 | set.insert(2); |
| 73 | |
| 74 | set = FnvHashSet::with_capacity_and_hasher(10, Default::default()); |
| 75 | set.insert(1); |
| 76 | set.insert(2); |
| 77 | ``` |
| 78 | |
| 79 | [chongo]: http://www.isthe.com/chongo/tech/comp/fnv/index.html |
| 80 | [faq]: https://www.rust-lang.org/en-US/faq.html#why-are-rusts-hashmaps-slow |
| 81 | [graphs]: https://cglab.ca/~abeinges/blah/hash-rs/ |