diff options
| author | bors <bors@rust-lang.org> | 2016-05-20 12:39:00 -0700 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2016-05-20 12:39:00 -0700 |
| commit | 179539f6eb61f75244a0dde641b6e4e09c0921ec (patch) | |
| tree | 088a911b82f99863d82a394d8fa5f67025de89c7 | |
| parent | 0352866da7098bdcc868fbc37246b48778ecf74a (diff) | |
| parent | eaeef3db0ea9bc100f4c17d708b55a29477ac634 (diff) | |
| download | rust-179539f6eb61f75244a0dde641b6e4e09c0921ec.tar.gz rust-179539f6eb61f75244a0dde641b6e4e09c0921ec.zip | |
Auto merge of #33318 - alexcrichton:hashmap-seed, r=aturon
std: Cache HashMap keys in TLS This is a rebase and extension of #31356 where we not only cache the keys in thread local storage but we also bump each key every time a new `HashMap` is created. This should give us a nice speed bost in creating hash maps along with retaining the property that all maps have a nondeterministic iteration order. Closes #27243
| -rw-r--r-- | src/libstd/collections/hash/map.rs | 29 |
1 files changed, 27 insertions, 2 deletions
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 9c688785741..e0a489bd2f9 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1667,8 +1667,33 @@ impl RandomState { #[allow(deprecated)] // rand #[stable(feature = "hashmap_build_hasher", since = "1.7.0")] pub fn new() -> RandomState { - let mut r = rand::thread_rng(); - RandomState { k0: r.gen(), k1: r.gen() } + // Historically this function did not cache keys from the OS and instead + // simply always called `rand::thread_rng().gen()` twice. In #31356 it + // was discovered, however, that because we re-seed the thread-local RNG + // from the OS periodically that this can cause excessive slowdown when + // many hash maps are created on a thread. To solve this performance + // trap we cache the first set of randomly generated keys per-thread. + // + // In doing this, however, we lose the property that all hash maps have + // nondeterministic iteration order as all of those created on the same + // thread would have the same hash keys. This property has been nice in + // the past as it allows for maximal flexibility in the implementation + // of `HashMap` itself. + // + // The constraint here (if there even is one) is just that maps created + // on the same thread have the same iteration order, and that *may* be + // relied upon even though it is not a documented guarantee at all of + // the `HashMap` type. In any case we've decided that this is reasonable + // for now, so caching keys thread-locally seems fine. + thread_local!(static KEYS: (u64, u64) = { + let r = rand::OsRng::new(); + let mut r = r.expect("failed to create an OS RNG"); + (r.gen(), r.gen()) + }); + + KEYS.with(|&(k0, k1)| { + RandomState { k0: k0, k1: k1 } + }) } } |
