@@ -101,11 +101,6 @@ private IEnumerable<IEarlyExit> GetEarlyExits(StringKeyProperties props, uint it
101101 if ( structureType == typeof ( ConditionalStructure < , > ) && itemCount <= 3 )
102102 yield break ;
103103
104- //Logic:
105- // - If all lengths are the same, we check against that (1 inst)
106- // - If lengths are dense, we do a range check (2 inst)
107- // - If the lengths are sparse, we use a bitset (4 inst)
108-
109104 LengthData lengthData = props . LengthData ;
110105
111106 MapStrategy lengthStrategy = GetLengthMapStrategy ( lengthData . LengthMap ) ;
@@ -148,22 +143,25 @@ private IEnumerable<IEarlyExit> GetEarlyExits(StringKeyProperties props, uint it
148143
149144 private IEnumerable < IEarlyExit > GetEarlyExits ( NumericKeyProperties < T > props , uint itemCount , Type structureType )
150145 {
151- //These don't support early exits
152- if ( structureType == typeof ( SingleValueStructure < , > ) || structureType == typeof ( BitSetStructure < , > ) || structureType == typeof ( RangeStructure < , > ) )
153- yield break ;
154-
155146 //There is no point to using early exists if there is just one item
156147 if ( itemCount == 1 )
157148 yield break ;
158149
150+ //These don't support early exits
151+ if ( structureType == typeof ( SingleValueStructure < , > ) || structureType == typeof ( BitSetStructure < , > ) || structureType == typeof ( RangeStructure < , > ) )
152+ yield break ;
153+
159154 //Conditional structures are not very useful with less than 3 items as checks costs more than the benefits
160155 if ( structureType == typeof ( ConditionalStructure < , > ) && itemCount <= 3 )
161156 yield break ;
162157
163- if ( ShouldApplyValueBitMask ( props , out ulong mask ) )
164- yield return new ValueBitMaskEarlyExit ( mask ) ;
158+ //If the min and max keys are equal, the generator can output a single length check conditional, which is better than any other method.
159+ if ( props . MinKeyValue . Equals ( props . MaxKeyValue ) )
160+ yield return new ValueRangeEarlyExit < T > ( props . MinKeyValue , props . MaxKeyValue ) ; // 1 op: val.Len != len
161+ else if ( IsBitMaskViable ( props , out ulong mask ) )
162+ yield return new ValueBitMaskEarlyExit ( mask ) ; // 2 ops: val & mask != 0
165163 else
166- yield return new ValueRangeEarlyExit < T > ( props . MinKeyValue , props . MaxKeyValue ) ;
164+ yield return new ValueRangeEarlyExit < T > ( props . MinKeyValue , props . MaxKeyValue ) ; // 3 ops: len < min || len > max
167165 }
168166
169167 private MapStrategy GetLengthMapStrategy ( LengthBitArray map )
@@ -176,7 +174,7 @@ private MapStrategy GetLengthMapStrategy(LengthBitArray map)
176174 return density >= _cfg . LengthMapMinDensity ? MapStrategy . Range : MapStrategy . Bitmap ;
177175 }
178176
179- private bool ShouldApplyValueBitMask ( NumericKeyProperties < T > props , out ulong mask )
177+ private bool IsBitMaskViable ( NumericKeyProperties < T > props , out ulong mask )
180178 {
181179 Type keyType = typeof ( T ) ;
182180
@@ -199,6 +197,7 @@ private bool ShouldApplyValueBitMask(NumericKeyProperties<T> props, out ulong ma
199197 }
200198
201199 mask = fullMask ^ props . BitMask ; // Invert the mask
200+
202201 if ( mask == 0 )
203202 return false ;
204203
0 commit comments