135 lines
4.4 KiB
C#
135 lines
4.4 KiB
C#
// -----------------------------------------------------------------------------
|
|
// file="SwissX86DisassemblyBench"
|
|
// Project: nFramework
|
|
// Copyright (c) Nitload.
|
|
// SPDX-License-Identifier: MIT
|
|
// -----------------------------------------------------------------------------
|
|
|
|
using BenchmarkDotNet.Attributes;
|
|
using BenchmarkDotNet.Diagnosers;
|
|
using Nitload.Common.HighPerformance.Memory;
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
using System.Runtime.Intrinsics.X86;
|
|
|
|
namespace Nitload.Benchmark
|
|
{
|
|
[DisassemblyDiagnoser(maxDepth: 3, exportHtml: true)]
|
|
public unsafe class SwissX86DisassemblyBench
|
|
{
|
|
|
|
private const int ResidentCount = 8192;
|
|
|
|
private byte* _buffer;
|
|
private L4.SwissTable _table;
|
|
private byte* _readBuffer;
|
|
private byte* _writeBuffer;
|
|
private L4.AddressSource _hitKey;
|
|
private L4.AddressSource _missKey;
|
|
private ulong _value;
|
|
|
|
[GlobalSetup]
|
|
public void Setup()
|
|
{
|
|
if (!Sse42.X64.IsSupported)
|
|
throw new PlatformNotSupportedException("The Swiss X86 disassembly probe requires x64 SSE4.2.");
|
|
|
|
_buffer = (byte*)NativeMemory.AlignedAlloc((nuint)L4.BufferSize, 64);
|
|
if (_buffer == null)
|
|
throw new OutOfMemoryException("Could not allocate Swiss disassembly buffers.");
|
|
|
|
_table = L4.SwissTable.Create(_buffer);
|
|
for (int index = 0; index < ResidentCount; index++)
|
|
{
|
|
if (!L4.SwissWriterX86.TryAddOrSet(_table.WriteBufferForLockFreeBenchmark,
|
|
MakeKey(index), (ulong)index + 1))
|
|
throw new InvalidOperationException($"Failed to seed Swiss key {index}.");
|
|
}
|
|
|
|
_table.SwapBuffers();
|
|
_readBuffer = _table.ReadBufferForLockFreeBenchmark;
|
|
_writeBuffer = _table.WriteBufferForLockFreeBenchmark;
|
|
for (int index = 0; index < ResidentCount; index++)
|
|
{
|
|
if (!L4.SwissWriterX86.TryAddOrSet(_writeBuffer, MakeKey(index), (ulong)index + 1))
|
|
throw new InvalidOperationException($"Failed to seed inactive Swiss key {index}.");
|
|
}
|
|
|
|
_hitKey = MakeKey(ResidentCount / 2);
|
|
_missKey = MakeKey(ResidentCount + 1);
|
|
_value = 0x1234_5678;
|
|
|
|
if (!L4.SwissReaderX86.TryGet(_readBuffer, _hitKey, out _) ||
|
|
L4.SwissReaderX86.TryGet(_readBuffer, _missKey, out _))
|
|
throw new InvalidOperationException("Swiss reader setup validation failed.");
|
|
}
|
|
|
|
[GlobalCleanup]
|
|
public void Cleanup()
|
|
{
|
|
_table.Dispose();
|
|
NativeMemory.AlignedFree(_buffer);
|
|
_buffer = null;
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool RawReaderHit()
|
|
{
|
|
return L4.SwissReaderX86.TryGet(_readBuffer, _hitKey, out _value);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool RawReaderMiss()
|
|
{
|
|
return L4.SwissReaderX86.TryGet(_readBuffer, _missKey, out _value);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool RawWriterUpsertExisting()
|
|
{
|
|
return L4.SwissWriterX86.TryAddOrSet(_writeBuffer, _hitKey, _value);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool RawWriterRemoveAndReinsert()
|
|
{
|
|
return L4.SwissWriterX86.TryRemove(_writeBuffer, _hitKey, out ulong previousValue) &&
|
|
L4.SwissWriterX86.TryAddOrSet(_writeBuffer, _hitKey, previousValue);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool TableReaderHit()
|
|
{
|
|
return _table.TryGet(_hitKey, out _value);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool TableReaderMiss()
|
|
{
|
|
return _table.TryGet(_missKey, out _value);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool TableWriterUpsertExisting()
|
|
{
|
|
return _table.TryAddOrSet(_hitKey, _value);
|
|
}
|
|
|
|
[Benchmark]
|
|
public bool TableWriterRemoveAndReinsert()
|
|
{
|
|
return _table.TryRemove(_hitKey, out ulong previousValue) &&
|
|
_table.TryAddOrSet(_hitKey, previousValue);
|
|
}
|
|
|
|
private static L4.AddressSource MakeKey(int index)
|
|
{
|
|
return new L4.AddressSource
|
|
{
|
|
Address = 0x1000_0000UL + ((ulong)index * 64UL),
|
|
Description = ((ulong)index * 0x9e37_79b9UL) ^ 0xd1b5_4a32_d192_ed03UL
|
|
};
|
|
}
|
|
|
|
}
|
|
} |