1- // hijack HashMap for performance
2- type HashMap < K , V > = std:: collections:: HashMap < K , V , rustc_hash:: FxBuildHasher > ;
3-
1+ use rustc_hash:: FxHashMap ;
42use std:: ops:: RangeInclusive ;
53
64use uucore:: error:: UResult ;
@@ -42,12 +40,17 @@ pub(crate) struct NonrepeatingIterator<'a> {
4240
4341enum Values {
4442 Full ( Vec < u64 > ) ,
45- Sparse ( RangeInclusive < u64 > , HashMap < u64 , u64 > ) ,
43+ Sparse ( RangeInclusive < u64 > , FxHashMap < u64 , u64 > ) ,
4644}
4745
4846impl < ' a > NonrepeatingIterator < ' a > {
4947 pub ( crate ) fn new ( range : RangeInclusive < u64 > , rng : & ' a mut WrappedRng ) -> Self {
50- let values = Values :: Sparse ( range, HashMap :: default ( ) ) ;
48+ let avoid_reallocation_bound = 128 ; // todo: optimize this
49+ let capacity = ( range. size_hint ( ) . 0 ) . min ( avoid_reallocation_bound) ;
50+ let values = Values :: Sparse (
51+ range,
52+ FxHashMap :: with_capacity_and_hasher ( capacity, rustc_hash:: FxBuildHasher ) ,
53+ ) ;
5154 NonrepeatingIterator { rng, values }
5255 }
5356
@@ -96,8 +99,7 @@ impl Iterator for NonrepeatingIterator<'_> {
9699 Values :: Full ( _) => ( ) ,
97100 Values :: Sparse ( range, _) if range. is_empty ( ) => return None ,
98101 Values :: Sparse ( range, items) => {
99- let range_len = range. size_hint ( ) . 0 as u64 ;
100- if items. len ( ) as u64 >= range_len / 8 {
102+ if items. len ( ) as u64 >= items. capacity ( ) as u64 {
101103 self . values = Values :: Full ( hashmap_to_vec ( range. clone ( ) , items) ) ;
102104 }
103105 }
@@ -107,7 +109,7 @@ impl Iterator for NonrepeatingIterator<'_> {
107109 }
108110}
109111
110- fn hashmap_to_vec ( range : RangeInclusive < u64 > , map : & HashMap < u64 , u64 > ) -> Vec < u64 > {
112+ fn hashmap_to_vec ( range : RangeInclusive < u64 > , map : & FxHashMap < u64 , u64 > ) -> Vec < u64 > {
111113 let lookup = |idx| * map. get ( & idx) . unwrap_or ( & idx) ;
112114 range. rev ( ) . map ( lookup) . collect ( )
113115}
0 commit comments