Skip to content

Commit 85aa9e7

Browse files
committed
Change generator to prefer value range for single length inputs
1 parent 6b051a4 commit 85aa9e7

1 file changed

Lines changed: 12 additions & 13 deletions

File tree

Src/FastData/Generators/GeneratorConfig.cs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)