about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2016-09-26 04:38:18 -0700
committerGitHub <noreply@github.com>2016-09-26 04:38:18 -0700
commit3bf4a7ad45bceef2e7ac666f4cbb41a37d6af763 (patch)
treee14c410297bb5a0deb14471046b46853354262f9 /src/libstd
parentb786976a158e79196254f489bb3a6f87e4d16a5a (diff)
parent4eb069c9811bc25d6ef9413de6058e5f14707816 (diff)
downloadrust-3bf4a7ad45bceef2e7ac666f4cbb41a37d6af763.tar.gz
rust-3bf4a7ad45bceef2e7ac666f4cbb41a37d6af763.zip
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.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/collections/hash/map.rs15
-rw-r--r--src/libstd/collections/hash/set.rs27
2 files changed, 34 insertions, 8 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index eb1653f18cb..29a79631535 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -2087,10 +2087,25 @@ 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);
 
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index ff56747fee6..a5089543980 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -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!)
 // =============================
 //
@@ -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
@@ -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`
@@ -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.
@@ -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() }
     }
 }
 
@@ -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() {