Skip to content

Commit dc73379

Browse files
committed
Hash up to 8 bytes at once with FxHasher
1 parent 29ffe51 commit dc73379

File tree

4 files changed

+29
-4
lines changed

4 files changed

+29
-4
lines changed

src/Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -1977,6 +1977,7 @@ dependencies = [
19771977
name = "rustc_data_structures"
19781978
version = "0.0.0"
19791979
dependencies = [
1980+
"byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
19801981
"cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
19811982
"ena 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)",
19821983
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",

src/librustc_data_structures/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ cfg-if = "0.1.2"
1717
stable_deref_trait = "1.0.0"
1818
parking_lot_core = "0.2.8"
1919
rustc-rayon = "0.1.0"
20+
byteorder = "1.1"
2021

2122
[dependencies.parking_lot]
2223
version = "0.5"

src/librustc_data_structures/fx.rs

+26-4
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ use std::collections::{HashMap, HashSet};
1212
use std::default::Default;
1313
use std::hash::{Hasher, Hash, BuildHasherDefault};
1414
use std::ops::BitXor;
15+
use std::mem::size_of;
16+
use byteorder::{ByteOrder, NativeEndian};
1517

1618
pub type FxHashMap<K, V> = HashMap<K, V, BuildHasherDefault<FxHasher>>;
1719
pub type FxHashSet<V> = HashSet<V, BuildHasherDefault<FxHasher>>;
@@ -37,6 +39,7 @@ pub fn FxHashSet<V: Hash + Eq>() -> FxHashSet<V> {
3739
/// out-performs an FNV-based hash within rustc itself -- the collision rate is
3840
/// similar or slightly worse than FNV, but the speed of the hash function
3941
/// itself is much higher because it works on up to 8 bytes at a time.
42+
#[derive(Copy, Clone)]
4043
pub struct FxHasher {
4144
hash: usize
4245
}
@@ -62,11 +65,30 @@ impl FxHasher {
6265

6366
impl Hasher for FxHasher {
6467
#[inline]
65-
fn write(&mut self, bytes: &[u8]) {
66-
for byte in bytes {
67-
let i = *byte;
68-
self.add_to_hash(i as usize);
68+
fn write(&mut self, mut bytes: &[u8]) {
69+
#[cfg(target_pointer_width = "32")]
70+
let read_usize = |bytes| NativeEndian::read_u32(bytes);
71+
#[cfg(target_pointer_width = "64")]
72+
let read_usize = |bytes| NativeEndian::read_u64(bytes);
73+
74+
let mut hash = *self;
75+
assert!(size_of::<usize>() <= 8);
76+
while bytes.len() >= size_of::<usize>() {
77+
hash.add_to_hash(read_usize(bytes) as usize);
78+
bytes = &bytes[size_of::<usize>()..];
6979
}
80+
if (size_of::<usize>() > 4) && (bytes.len() >= 4) {
81+
hash.add_to_hash(NativeEndian::read_u32(bytes) as usize);
82+
bytes = &bytes[4..];
83+
}
84+
if (size_of::<usize>() > 2) && bytes.len() >= 2 {
85+
hash.add_to_hash(NativeEndian::read_u16(bytes) as usize);
86+
bytes = &bytes[2..];
87+
}
88+
if (size_of::<usize>() > 1) && bytes.len() >= 1 {
89+
hash.add_to_hash(bytes[0] as usize);
90+
}
91+
*self = hash;
7092
}
7193

7294
#[inline]

src/librustc_data_structures/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#![cfg_attr(unix, feature(libc))]
3333
#![cfg_attr(test, feature(test))]
3434

35+
extern crate byteorder;
3536
extern crate core;
3637
extern crate ena;
3738
#[macro_use]

0 commit comments

Comments
 (0)