Skip to content

Commit 96c4e42

Browse files
committed
Add write_* methods for DefaultHasher, SipHasher, SipHasher13, sip::Hasher.
`sip::Hasher::short_write` is currently unused. It is called by `sip::Hasher::write_{u8,usize}`, but those methods are also unused, because `DefaultHasher`, `SipHasher` and `SipHasher13` don't implement any of the `write_xyz` methods, so all their write operations end up calling `sip::Hasher::write`. I confirmed this by inserting a `panic!` in `sip::Hasher::short_write` and running the tests -- they all passed. This commit adds all the `write_xyz` methods to `DefaultHasher`, `SipHasher`, `SipHasher13` and `sip::Hasher`, which means that `short_write` will be used for all of them. (I haven't properly implemented 128-bit writes in `sip::Hasher` and `SipHasher128`. That could be a follow-up if something thinks it is important.) Some microbenchmarks I wrote show that this commit speeds up default hashing of integers by about 2.5x, and can speed up hash tables that use `DefaultHasher` and have keys that contain integers by up to 30%, though the exact amount depends heavily on the details of the keys and how the table is used. This makes default `Hash{Map,Set}` much more likely to be competitive with `FxHash{Map,Set}`.
1 parent f272983 commit 96c4e42

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed

src/libcore/hash/sip.rs

+164
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,66 @@ impl<S: Sip> Hasher<S> {
296296

297297
#[stable(feature = "rust1", since = "1.0.0")]
298298
impl super::Hasher for SipHasher {
299+
#[inline]
300+
fn write_u8(&mut self, i: u8) {
301+
self.0.hasher.write_u8(i);
302+
}
303+
304+
#[inline]
305+
fn write_u16(&mut self, i: u16) {
306+
self.0.hasher.write_u16(i);
307+
}
308+
309+
#[inline]
310+
fn write_u32(&mut self, i: u32) {
311+
self.0.hasher.write_u32(i);
312+
}
313+
314+
#[inline]
315+
fn write_u64(&mut self, i: u64) {
316+
self.0.hasher.write_u64(i);
317+
}
318+
319+
#[inline]
320+
fn write_u128(&mut self, i: u128) {
321+
self.0.hasher.write_u128(i);
322+
}
323+
324+
#[inline]
325+
fn write_usize(&mut self, i: usize) {
326+
self.0.hasher.write_usize(i);
327+
}
328+
329+
#[inline]
330+
fn write_i8(&mut self, i: i8) {
331+
self.0.hasher.write_i8(i);
332+
}
333+
334+
#[inline]
335+
fn write_i16(&mut self, i: i16) {
336+
self.0.hasher.write_i16(i);
337+
}
338+
339+
#[inline]
340+
fn write_i32(&mut self, i: i32) {
341+
self.0.hasher.write_i32(i);
342+
}
343+
344+
#[inline]
345+
fn write_i64(&mut self, i: i64) {
346+
self.0.hasher.write_i64(i);
347+
}
348+
349+
#[inline]
350+
fn write_i128(&mut self, i: i128) {
351+
self.0.hasher.write_i128(i);
352+
}
353+
354+
#[inline]
355+
fn write_isize(&mut self, i: isize) {
356+
self.0.hasher.write_isize(i);
357+
}
358+
299359
#[inline]
300360
fn write(&mut self, msg: &[u8]) {
301361
self.0.hasher.write(msg)
@@ -309,6 +369,66 @@ impl super::Hasher for SipHasher {
309369

310370
#[unstable(feature = "hashmap_internals", issue = "none")]
311371
impl super::Hasher for SipHasher13 {
372+
#[inline]
373+
fn write_u8(&mut self, i: u8) {
374+
self.hasher.write_u8(i);
375+
}
376+
377+
#[inline]
378+
fn write_u16(&mut self, i: u16) {
379+
self.hasher.write_u16(i);
380+
}
381+
382+
#[inline]
383+
fn write_u32(&mut self, i: u32) {
384+
self.hasher.write_u32(i);
385+
}
386+
387+
#[inline]
388+
fn write_u64(&mut self, i: u64) {
389+
self.hasher.write_u64(i);
390+
}
391+
392+
#[inline]
393+
fn write_u128(&mut self, i: u128) {
394+
self.hasher.write_u128(i);
395+
}
396+
397+
#[inline]
398+
fn write_usize(&mut self, i: usize) {
399+
self.hasher.write_usize(i);
400+
}
401+
402+
#[inline]
403+
fn write_i8(&mut self, i: i8) {
404+
self.hasher.write_i8(i);
405+
}
406+
407+
#[inline]
408+
fn write_i16(&mut self, i: i16) {
409+
self.hasher.write_i16(i);
410+
}
411+
412+
#[inline]
413+
fn write_i32(&mut self, i: i32) {
414+
self.hasher.write_i32(i);
415+
}
416+
417+
#[inline]
418+
fn write_i64(&mut self, i: i64) {
419+
self.hasher.write_i64(i);
420+
}
421+
422+
#[inline]
423+
fn write_i128(&mut self, i: i128) {
424+
self.hasher.write_i128(i);
425+
}
426+
427+
#[inline]
428+
fn write_isize(&mut self, i: isize) {
429+
self.hasher.write_isize(i);
430+
}
431+
312432
#[inline]
313433
fn write(&mut self, msg: &[u8]) {
314434
self.hasher.write(msg)
@@ -326,11 +446,55 @@ impl<S: Sip> super::Hasher for Hasher<S> {
326446
self.short_write(i, i as u64);
327447
}
328448

449+
#[inline]
450+
fn write_u16(&mut self, i: u16) {
451+
self.short_write(i, i.to_le() as u64);
452+
}
453+
454+
#[inline]
455+
fn write_u32(&mut self, i: u32) {
456+
self.short_write(i, i.to_le() as u64);
457+
}
458+
459+
#[inline]
460+
fn write_u64(&mut self, i: u64) {
461+
self.short_write(i, i.to_le() as u64);
462+
}
463+
464+
// `write_u128` is currently unimplemented.
465+
329466
#[inline]
330467
fn write_usize(&mut self, i: usize) {
331468
self.short_write(i, i.to_le() as u64);
332469
}
333470

471+
#[inline]
472+
fn write_i8(&mut self, i: i8) {
473+
self.short_write(i, i as u8 as u64);
474+
}
475+
476+
#[inline]
477+
fn write_i16(&mut self, i: i16) {
478+
self.short_write(i, (i as u16).to_le() as u64);
479+
}
480+
481+
#[inline]
482+
fn write_i32(&mut self, i: i32) {
483+
self.short_write(i, (i as u32).to_le() as u64);
484+
}
485+
486+
#[inline]
487+
fn write_i64(&mut self, i: i64) {
488+
self.short_write(i, (i as u64).to_le() as u64);
489+
}
490+
491+
// `write_i128` is currently unimplemented.
492+
493+
#[inline]
494+
fn write_isize(&mut self, i: isize) {
495+
self.short_write(i, (i as usize).to_le() as u64);
496+
}
497+
334498
#[inline]
335499
fn write(&mut self, msg: &[u8]) {
336500
let length = msg.len();

src/librustc_data_structures/sip128.rs

+4
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ impl Hasher for SipHasher128 {
235235
self.short_write(i, i.to_le() as u64);
236236
}
237237

238+
// `write_u128` is currently unimplemented.
239+
238240
#[inline]
239241
fn write_usize(&mut self, i: usize) {
240242
self.short_write(i, i.to_le() as u64);
@@ -260,6 +262,8 @@ impl Hasher for SipHasher128 {
260262
self.short_write(i, (i as u64).to_le() as u64);
261263
}
262264

265+
// `write_i128` is currently unimplemented.
266+
263267
#[inline]
264268
fn write_isize(&mut self, i: isize) {
265269
self.short_write(i, (i as usize).to_le() as u64);

src/libstd/collections/hash/map.rs

+60
Original file line numberDiff line numberDiff line change
@@ -2515,6 +2515,66 @@ impl Default for DefaultHasher {
25152515

25162516
#[stable(feature = "hashmap_default_hasher", since = "1.13.0")]
25172517
impl Hasher for DefaultHasher {
2518+
#[inline]
2519+
fn write_u8(&mut self, i: u8) {
2520+
self.0.write_u8(i);
2521+
}
2522+
2523+
#[inline]
2524+
fn write_u16(&mut self, i: u16) {
2525+
self.0.write_u16(i);
2526+
}
2527+
2528+
#[inline]
2529+
fn write_u32(&mut self, i: u32) {
2530+
self.0.write_u32(i);
2531+
}
2532+
2533+
#[inline]
2534+
fn write_u64(&mut self, i: u64) {
2535+
self.0.write_u64(i);
2536+
}
2537+
2538+
#[inline]
2539+
fn write_u128(&mut self, i: u128) {
2540+
self.0.write_u128(i);
2541+
}
2542+
2543+
#[inline]
2544+
fn write_usize(&mut self, i: usize) {
2545+
self.0.write_usize(i);
2546+
}
2547+
2548+
#[inline]
2549+
fn write_i8(&mut self, i: i8) {
2550+
self.0.write_i8(i);
2551+
}
2552+
2553+
#[inline]
2554+
fn write_i16(&mut self, i: i16) {
2555+
self.0.write_i16(i);
2556+
}
2557+
2558+
#[inline]
2559+
fn write_i32(&mut self, i: i32) {
2560+
self.0.write_i32(i);
2561+
}
2562+
2563+
#[inline]
2564+
fn write_i64(&mut self, i: i64) {
2565+
self.0.write_i64(i);
2566+
}
2567+
2568+
#[inline]
2569+
fn write_i128(&mut self, i: i128) {
2570+
self.0.write_i128(i);
2571+
}
2572+
2573+
#[inline]
2574+
fn write_isize(&mut self, i: isize) {
2575+
self.0.write_isize(i);
2576+
}
2577+
25182578
#[inline]
25192579
fn write(&mut self, msg: &[u8]) {
25202580
self.0.write(msg)

0 commit comments

Comments
 (0)