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:
commit
3bf4a7ad45
|
@ -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);
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue