Auto merge of #36734 - nnethercote:fix-HashSet-sizing, r=Aatch

Don't allocate during default HashSet creation.

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.
This commit is contained in:
bors 2016-09-26 04:38:18 -07:00 committed by GitHub
commit 3bf4a7ad45
2 changed files with 34 additions and 8 deletions

View File

@ -2087,9 +2087,24 @@ fn assert_covariance() {
mod test_map { mod test_map {
use super::HashMap; use super::HashMap;
use super::Entry::{Occupied, Vacant}; use super::Entry::{Occupied, Vacant};
use super::RandomState;
use cell::RefCell; use cell::RefCell;
use rand::{thread_rng, Rng}; 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] #[test]
fn test_create_capacity_zero() { fn test_create_capacity_zero() {
let mut m = HashMap::with_capacity(0); let mut m = HashMap::with_capacity(0);

View File

@ -17,8 +17,6 @@ use ops::{BitOr, BitAnd, BitXor, Sub};
use super::Recover; use super::Recover;
use super::map::{self, HashMap, Keys, RandomState}; use super::map::{self, HashMap, Keys, RandomState};
const INITIAL_CAPACITY: usize = 32;
// Future Optimization (FIXME!) // Future Optimization (FIXME!)
// ============================= // =============================
// //
@ -118,7 +116,7 @@ impl<T: Hash + Eq> HashSet<T, RandomState> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> HashSet<T, RandomState> { 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 /// Creates an empty HashSet with space for at least `n` elements in
@ -163,7 +161,7 @@ impl<T, S> HashSet<T, S>
#[inline] #[inline]
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_hasher(hasher: S) -> HashSet<T, S> { 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` /// Creates an empty HashSet with space for at least `capacity`
@ -188,9 +186,7 @@ impl<T, S> HashSet<T, S>
#[stable(feature = "hashmap_build_hasher", since = "1.7.0")] #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
pub fn with_capacity_and_hasher(capacity: usize, hasher: S) pub fn with_capacity_and_hasher(capacity: usize, hasher: S)
-> HashSet<T, S> { -> HashSet<T, S> {
HashSet { HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
map: HashMap::with_capacity_and_hasher(capacity, hasher),
}
} }
/// Returns a reference to the set's hasher. /// Returns a reference to the set's hasher.
@ -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. /// Creates an empty `HashSet<T, S>` with the `Default` value for the hasher.
fn default() -> HashSet<T, S> { fn default() -> HashSet<T, S> {
HashSet::with_hasher(Default::default()) HashSet { map: HashMap::default() }
} }
} }
@ -1069,6 +1065,21 @@ fn assert_covariance() {
#[cfg(test)] #[cfg(test)]
mod test_set { mod test_set {
use super::HashSet; 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] #[test]
fn test_disjoint() { fn test_disjoint() {