Skip to content

Commit d994700

Browse files
committed
nice capacity boundaries
1 parent 32cbe18 commit d994700

File tree

1 file changed

+12
-25
lines changed

1 file changed

+12
-25
lines changed

src/FastExpressionCompiler/ImTools.cs

Lines changed: 12 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -841,8 +841,9 @@ public interface Use<T> { }
841841
public static class SmallMap
842842
{
843843
internal const byte MinFreeCapacityShift = 3; // e.g. for the capacity 16: 16 >> 3 => 2, 12.5% of the free hash slots (it does not mean the entries free slot)
844-
internal const byte MinHashesCapacityBitShift = 4; // 1 << 4 == 16
845-
internal const int IndexMask = (1 << MinHashesCapacityBitShift) - 1; // 0b00000000000000000000000000001111
844+
internal const byte MinHashesCapacityBitShift = 3; // 1 << 3 == 8
845+
internal const byte DefaultHashesCapacityBitShift = 4; // 1 << 4 == 16, means the default capacity is 16 int hashes
846+
internal const int IndexMask = (1 << DefaultHashesCapacityBitShift) - 1; // 0b00000000000000000000000000001111
846847
/// <summary>Upper hash bits spent on storing the probes, e.g. 5 bits mean 31 probes max.</summary>
847848
public const byte ProbeBits = 5;
848849
internal const byte NotShiftedProbeCountMask = (1 << ProbeBits) - 1; // 0b00000000000000000000000000011111
@@ -895,20 +896,6 @@ public struct Entry<K> : IEntry<K>
895896
/// <summary>Binary representation of the `int`</summary>
896897
public static string ToB(int x) => System.Convert.ToString(x, 2).PadLeft(32, '0');
897898

898-
// [MethodImpl((MethodImplOptions)256)]
899-
// #if NET7_0_OR_GREATER
900-
// internal static ref int NextHashRef(ref int start, int distance) => ref Unsafe.Add(ref start, distance);
901-
// #else
902-
// internal static ref int NextHashRef(ref int[] start, int distance) => ref start[distance];
903-
// #endif
904-
905-
// [MethodImpl((MethodImplOptions)256)]
906-
// #if NET7_0_OR_GREATER
907-
// internal static int NextHash(ref int start, int distance) => Unsafe.Add(ref start, distance);
908-
// #else
909-
// internal static int NextHash(ref int[] start, int distance) => start[distance];
910-
// #endif
911-
912899
/// <summary>Abstraction to configure your own entries data structure. Check the derived types for the examples</summary>
913900
public interface IEntries<K, TEntry, TEq>
914901
where TEntry : struct, IEntry<K>
@@ -1098,12 +1085,12 @@ public struct SmallMap<K, TEntry, TEq, TStackCap, TStackHashes, TStackEntries, T
10981085
internal int[] _packedHashesAndIndexes;
10991086

11001087
#pragma warning disable IDE0044 // it tries to make entries readonly but they should stay modify-able to prevent its defensive struct copying
1088+
#pragma warning disable CS0649 // field is never assigned to, and will always have its default value
11011089
internal TEntries _entries;
1102-
#pragma warning restore IDE0044
1103-
#pragma warning disable CS0649 // Field 'SmallMap<K, V, TEq, TStack, TEntries>.Stack' is never assigned to, and will always have its default value
11041090
internal TStackHashes _stackHashes;
11051091
internal TStackEntries StackEntries;
11061092
#pragma warning restore CS0649
1093+
#pragma warning restore IDE0044
11071094

11081095
/// <summary>Capacity bits</summary>
11091096
public int CapacityBitShift => _capacityBitShift;
@@ -1120,12 +1107,12 @@ public struct SmallMap<K, TEntry, TEq, TStackCap, TStackHashes, TStackEntries, T
11201107
/// <summary>Capacity calculates as `1 leftShift capacityBitShift`</summary>
11211108
public SmallMap(byte capacityBitShift)
11221109
{
1123-
_capacityBitShift = capacityBitShift;
1110+
// Keep the capacity at least 8 for SIMD Vector256, etc., etc, if you need less space use Stack for that
1111+
_capacityBitShift = capacityBitShift < MinHashesCapacityBitShift ? MinHashesCapacityBitShift : capacityBitShift;
11241112

1125-
// the overflow tail to the hashes is the size of log2N where N==capacityBitShift,
1113+
// The overflow tail to the hashes is the size of log2N where N==capacityBitShift,
11261114
// it is probably fine to have the check for the overflow of capacity because it will be mis-predicted only once at the end of loop (it even rarely for the lookup)
11271115
_packedHashesAndIndexes = new int[1 << capacityBitShift];
1128-
_entries = default;
11291116
_entries.Init(capacityBitShift);
11301117
}
11311118

@@ -1270,8 +1257,8 @@ public ref TEntry AddOrGetEntryRef(K key, out bool found)
12701257
// So the values on the stack are guarantied to be stable from the beginning of the map creation,
12711258
// because they are not copied when the Entries need to Resize (depending on the TEntries implementation).
12721259

1273-
_capacityBitShift = MinHashesCapacityBitShift;
1274-
_packedHashesAndIndexes = new int[1 << MinHashesCapacityBitShift];
1260+
_capacityBitShift = DefaultHashesCapacityBitShift;
1261+
_packedHashesAndIndexes = new int[1 << DefaultHashesCapacityBitShift];
12751262

12761263
for (var i = 0; i < StackEntries.Capacity; ++i)
12771264
AddJustHashAndEntryIndexWithoutResizing(default(TEq).GetHashCode(GetSurePresentEntryRef(i).Key), i);
@@ -1350,8 +1337,8 @@ public ref TEntry AddSureAbsentDefaultEntryAndGetRef(K key)
13501337
return ref newEntry;
13511338
}
13521339

1353-
_capacityBitShift = MinHashesCapacityBitShift;
1354-
_packedHashesAndIndexes = new int[1 << MinHashesCapacityBitShift];
1340+
_capacityBitShift = DefaultHashesCapacityBitShift;
1341+
_packedHashesAndIndexes = new int[1 << DefaultHashesCapacityBitShift];
13551342

13561343
for (var i = 0; i < StackEntries.Capacity; ++i)
13571344
AddJustHashAndEntryIndexWithoutResizing(default(TEq).GetHashCode(GetSurePresentEntryRef(i).Key), i);

0 commit comments

Comments
 (0)