Skip to content

Commit

Permalink
hash collision benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
Scooletz committed Jul 26, 2024
1 parent a69bd6c commit fe2ccd9
Showing 1 changed file with 70 additions and 1 deletion.
71 changes: 70 additions & 1 deletion src/Paprika.Benchmarks/SlottedArrayBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,15 @@ private const int
private readonly void* _keys;
private readonly void* _map;

// Hash colliding
private const int HashCollidingKeyCount = 32;

// Use first and last as opportunity to collide
private const int BytesPerKeyHashColliding = 3;
private readonly void* _hashCollidingKeys;
private readonly void* _hashCollidingMap;


public SlottedArrayBenchmarks()
{
// Create keys
Expand Down Expand Up @@ -45,7 +54,37 @@ public SlottedArrayBenchmarks()
throw new Exception("Not enough memory");
}
}

// Hash colliding
_hashCollidingKeys = AllocAlignedPage();

// Create keys so that two consecutive ones share the hash.
// This should make it somewhat realistic where there are some collisions but not a lot of them.
var hashCollidingKeys = new Span<byte>(_hashCollidingKeys, Page.PageSize);
for (byte i = 0; i < HashCollidingKeyCount; i++)
{
// 0th divide by 2 to collide
hashCollidingKeys[i * BytesPerKeyHashColliding] = (byte)(i / 2);

// 1th differentiate with the first
hashCollidingKeys[i * BytesPerKeyHashColliding + 1] = i;

// 2nd divide by 2 to collide
hashCollidingKeys[i * BytesPerKeyHashColliding + 2] = (byte)(i / 2);
}

_hashCollidingMap = AllocAlignedPage();

var hashColliding = new SlottedArray(new Span<byte>(_hashCollidingMap, Page.PageSize));
for (byte i = 0; i < HashCollidingKeyCount; i++)
{
value[0] = i;
if (hashColliding.TrySet(GetHashCollidingKey(i), value) == false)
{
throw new Exception("Not enough memory");
}
}

return;

static void* AllocAlignedPage()
Expand Down Expand Up @@ -81,6 +120,26 @@ public int TryGet(byte index, bool odd)
if (map.TryGet(key, out _)) count += 1;
return count;
}

[Benchmark(OperationsPerInvoke = 4)]
[Arguments((byte)1)]
[Arguments((byte)2)]
[Arguments((byte)3)]
[Arguments((byte)4)]
[Arguments((byte)30)]
[Arguments((byte)31)]
public int TryGet_With_Hash_Collisions(byte index)
{
var map = new SlottedArray(new Span<byte>(_hashCollidingMap, Page.PageSize));
var key = GetHashCollidingKey(index);

var count = 0;
if (map.TryGet(key, out _)) count += 1;
if (map.TryGet(key, out _)) count += 1;
if (map.TryGet(key, out _)) count += 1;
if (map.TryGet(key, out _)) count += 1;
return count;
}

[Benchmark(OperationsPerInvoke = 2)]
[Arguments(0, 0)]
Expand Down Expand Up @@ -129,9 +188,19 @@ public int EnumerateAll()

private NibblePath GetKey(byte i, bool odd)
{
var span = new Span<byte>(_keys, Page.PageSize);

var span = new Span<byte>(_keys, BytesPerKey * KeyCount);
var slice = span.Slice(i * BytesPerKey, BytesPerKey);

return NibblePath.FromKey(slice, odd ? 1 : 0, 4);
}

private NibblePath GetHashCollidingKey(byte i)
{
var span = new Span<byte>(_hashCollidingKeys, BytesPerKeyHashColliding * HashCollidingKeyCount);
var slice = span.Slice(i * BytesPerKeyHashColliding, BytesPerKeyHashColliding);

// Use full key
return NibblePath.FromKey(slice, 0, BytesPerKeyHashColliding * NibblePath.NibblePerByte);
}
}

0 comments on commit fe2ccd9

Please sign in to comment.