Skip to content

Commit

Permalink
Don't allocate during default HashSet creation.
Browse files Browse the repository at this point in the history
The following `HashMap` creation functions don't allocate heap storage for elements.
```
HashMap::new()
HashMap::default()
HashMap::with_hasher()
```
This is good, because it's surprisingly common to create a HashMap and never
use it. So that case should be cheap.

However, `HashSet` does not have the same behaviour. The corresponding creation
functions *do* allocate heap storage for the default number of non-zero
elements (which is 32 slots for 29 elements).
```
HashMap::new()
HashMap::default()
HashMap::with_hasher()
```
This commit gives `HashSet` the same behaviour as `HashMap`, by simply calling
the corresponding `HashMap` functions (something `HashSet` already does for
`with_capacity` and `with_capacity_and_hasher`). It also reformats one existing
`HashSet` construction to use a consistent single-line format.

This speeds up rustc itself by 1.01--1.04x on most of the non-tiny
rustc-benchmarks.
  • Loading branch information
nnethercote committed Sep 26, 2016
1 parent 458f411 commit 4eb069c
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 8 deletions.
15 changes: 15 additions & 0 deletions src/libstd/collections/hash/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2087,9 +2087,24 @@ fn assert_covariance() {
mod test_map {
use super::HashMap;
use super::Entry::{Occupied, Vacant};
use super::RandomState;
use cell::RefCell;
use rand::{thread_rng, Rng};

#[test]
fn test_create_capacities() {
type HM = HashMap<i32, i32>;

let m = HM::new();
assert_eq!(m.capacity(), 0);

let m = HM::default();
assert_eq!(m.capacity(), 0);

let m = HM::with_hasher(RandomState::new());
assert_eq!(m.capacity(), 0);
}

#[test]
fn test_create_capacity_zero() {
let mut m = HashMap::with_capacity(0);
Expand Down
27 changes: 19 additions & 8 deletions src/libstd/collections/hash/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ use ops::{BitOr, BitAnd, BitXor, Sub};
use super::Recover;
use super::map::{self, HashMap, Keys, RandomState};

const INITIAL_CAPACITY: usize = 32;

// Future Optimization (FIXME!)
// =============================
//
Expand Down Expand Up @@ -118,7 +116,7 @@ impl<T: Hash + Eq> HashSet<T, RandomState> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> HashSet<T, RandomState> {
HashSet::with_capacity(INITIAL_CAPACITY)
HashSet { map: HashMap::new() }
}

/// Creates an empty HashSet with space for at least `n` elements in
Expand Down Expand Up @@ -163,7 +161,7 @@ impl<T, S> HashSet<T, S>
#[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_hasher(hasher: S) -> HashSet<T, S> {
HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
HashSet { map: HashMap::with_hasher(hasher) }
}

/// Creates an empty HashSet with space for at least `capacity`
Expand All @@ -188,9 +186,7 @@ impl<T, S> HashSet<T, S>
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_capacity_and_hasher(capacity: usize, hasher: S)
-> HashSet<T, S> {
HashSet {
map: HashMap::with_capacity_and_hasher(capacity, hasher),
}
HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
}

/// Returns a reference to the set's hasher.
Expand Down Expand Up @@ -667,7 +663,7 @@ impl<T, S> Default for HashSet<T, S>
{
/// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
fn default() -> HashSet<T, S> {
HashSet::with_hasher(Default::default())
HashSet { map: HashMap::default() }
}
}

Expand Down Expand Up @@ -1069,6 +1065,21 @@ fn assert_covariance() {
#[cfg(test)]
mod test_set {
use super::HashSet;
use super::super::map::RandomState;

#[test]
fn test_create_capacities() {
type HS = HashSet<i32>;

let s = HS::new();
assert_eq!(s.capacity(), 0);

let s = HS::default();
assert_eq!(s.capacity(), 0);

let s = HS::with_hasher(RandomState::new());
assert_eq!(s.capacity(), 0);
}

#[test]
fn test_disjoint() {
Expand Down

0 comments on commit 4eb069c

Please sign in to comment.