6161 A : Aggregator ,
6262{
6363 shards_count : usize ,
64+ shift_by : usize ,
6465 // for performance reasons, no_attribs tracker
6566 no_attribs : NoAttribs < A > ,
6667 // for performance reasons, to handle attributes in the provided order
@@ -78,15 +79,20 @@ where
7879 A : Aggregator ,
7980{
8081 fn new ( config : A :: InitConfig ) -> Self {
81- let shards_count = std:: thread:: available_parallelism ( )
82+ // mostly inspired by dashmap crate
83+ let shards_count = ( std:: thread:: available_parallelism ( )
8284 . map ( |v| v. get ( ) )
8385 . unwrap_or ( 1 )
84- * 4 ;
86+ * 4 )
87+ . next_power_of_two ( ) ;
88+ let shift_by =
89+ ( std:: mem:: size_of :: < usize > ( ) * 8 ) - ( shards_count. trailing_zeros ( ) as usize ) ;
8590 let mut all_attribs = Vec :: with_capacity ( shards_count) ;
8691 all_attribs. resize_with ( shards_count, || {
8792 CachePadded :: new ( RwLock :: new ( HashMap :: default ( ) ) )
8893 } ) ;
8994 ValueMap {
95+ shift_by,
9096 shards_count,
9197 no_attribs : NoAttribs {
9298 tracker : A :: create ( & config) ,
@@ -107,7 +113,7 @@ where
107113
108114 let attributes = Hashed :: from_borrowed ( attributes) ;
109115
110- let shard = ( attributes. hash_value ( ) % self . shards_count as u64 ) as usize ;
116+ let shard = self . determine_shard ( attributes. hash_value ( ) ) ;
111117
112118 // Try to retrieve and update the tracker with the attributes in the provided order first
113119 match self . all_attribs [ shard] . read ( ) {
@@ -219,6 +225,11 @@ where
219225 dest. push ( map_fn ( attrs. into_inner_owned ( ) , tracker) ) ;
220226 }
221227 }
228+
229+ fn determine_shard ( & self , hash : u64 ) -> usize {
230+ // Leave the high 7 bits for the HashBrown SIMD tag.
231+ ( ( hash as usize ) << 7 ) >> self . shift_by
232+ }
222233}
223234
224235/// Clear and allocate exactly required amount of space for all attribute-sets
0 commit comments