diff --git a/src/LightningDB.Benchmarks/BenchmarkBase.cs b/src/LightningDB.Benchmarks/BenchmarkBase.cs new file mode 100644 index 0000000..5870c90 --- /dev/null +++ b/src/LightningDB.Benchmarks/BenchmarkBase.cs @@ -0,0 +1,92 @@ +using System; +using System.Dynamic; +using System.IO; + +using BenchmarkDotNet; +using BenchmarkDotNet.Attributes; + +using LightningDB; + +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace LightningDB.Benchmarks +{ + public abstract class BenchmarksBase + { + public LightningEnvironment Env { get; set; } + public LightningDatabase DB { get; set; } + + [GlobalSetup] + public void GlobalSetup() + { + Console.WriteLine("Global Setup Begin"); + + const string Path = "TestDirectory"; + + if (Directory.Exists(Path)) + Directory.Delete(Path, true); + + Env = new LightningEnvironment(Path) { + MaxDatabases = 1 + }; + + Env.Open(); + + using (var tx = Env.BeginTransaction()) { + DB = tx.OpenDatabase(); + tx.Commit(); + } + + RunSetup(); + + Console.WriteLine("Global Setup End"); + } + + public abstract void RunSetup(); + + [GlobalCleanup] + public void GlobalCleanup() + { + Console.WriteLine("Global Cleanup Begin"); + + try { + DB.Dispose(); + Env.Dispose(); + } + catch(Exception ex) { + Console.WriteLine(ex.ToString()); + } + Console.WriteLine("Global Cleanup End"); + } + } + + public abstract class RWBenchmarksBase : BenchmarksBase + { + //***** Argument Matrix Start *****// + [Params(1, 100, 1000)] + public int OpsPerTransaction { get; set; } + + [Params(8, 64, 256)] + public int ValueSize { get; set; } + + [Params(KeyOrdering.Sequential)] + public KeyOrdering KeyOrder { get; set; } + + //***** Argument Matrix End *****// + + + + //***** Test Values Begin *****// + + protected byte[] ValueBuffer { get; private set; } + protected KeyBatch KeyBuffers { get; private set; } + + //***** Test Values End *****// + + public override void RunSetup() + { + ValueBuffer = new byte[ValueSize]; + KeyBuffers = KeyBatch.Generate(OpsPerTransaction, KeyOrder); + } + } +} diff --git a/src/LightningDB.Benchmarks/Benchmarks.cs b/src/LightningDB.Benchmarks/Benchmarks.cs deleted file mode 100644 index 9f93650..0000000 --- a/src/LightningDB.Benchmarks/Benchmarks.cs +++ /dev/null @@ -1,112 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Dynamic; -using System.IO; -using System.Runtime.InteropServices; -using BenchmarkDotNet; -using BenchmarkDotNet.Attributes; - -using LightningDB; - -using Microsoft.CodeAnalysis.CSharp.Syntax; - -namespace LightningDB.Benchmarks -{ - public abstract class BenchmarksBase - { - public LightningEnvironment Env { get; set; } - public LightningDatabase DB { get; set; } - - [GlobalSetup] - public void GlobalSetup() - { - const string Path = "TestDirectory"; - - if (Directory.Exists(Path)) - Directory.Delete(Path, true); - - Env = new LightningEnvironment(Path) { - MaxDatabases = 1 - }; - - Env.Open(); - - using var tx = Env.BeginTransaction(); - DB = tx.OpenDatabase(); - - RunSetup(); - } - - public abstract void RunSetup(); - - [GlobalCleanup] - public void GlobalCleanup() - { - DB.Dispose(); - Env.Dispose(); - } - } - - [MemoryDiagnoser] - public class WriteBenchmarks : BenchmarksBase - { - [Params(1, 10, 100)] - public int BatchSize { get; set; } - - - [Params(4, 8, 64, 256)] - public int WriteSize { get; set; } - - - //[Params(true, false)] - [Params(true)] - public bool SequentialKeys { get; set; } - - public byte[] ValueBuffer { get; set; } - public byte[][] KeyBuffers { get; set; } - - - - public override void RunSetup() - { - ValueBuffer = new byte[WriteSize]; - KeyBuffers = new byte[BatchSize][]; - - if(SequentialKeys) { - for(int i = 0; i < BatchSize; i++) { - var key = new byte[4]; - MemoryMarshal.Write(key, ref i); - KeyBuffers[i] = key; - } - } - else { - var random = new Random(0); - var seen = new HashSet(BatchSize); - - for (int i = 0; i < BatchSize;) { - var keyValue = random.Next(0, BatchSize); - - if (seen.Add(keyValue)) { - var key = new byte[4]; - MemoryMarshal.Write(key, ref keyValue); - KeyBuffers[i++] = key; - } - else - continue; - } - } - } - - - [Benchmark] - public void Write() - { - using(var transaction = Env.BeginTransaction()) - { - for (int i = 0; i < BatchSize; i++) { - transaction.Put(DB, KeyBuffers[i], ValueBuffer); - } - } - } - } -} diff --git a/src/LightningDB.Benchmarks/KeyBatch.cs b/src/LightningDB.Benchmarks/KeyBatch.cs new file mode 100644 index 0000000..4979589 --- /dev/null +++ b/src/LightningDB.Benchmarks/KeyBatch.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace LightningDB.Benchmarks +{ + + public enum KeyOrdering + { + Sequential, + Random + } + + /// + /// A collection of 4 byte key arrays + /// + public class KeyBatch + { + private KeyBatch(byte[][] buffers) + { + Buffers = buffers; + } + + public byte[][] Buffers { get; } + + + public int Count => Buffers.Length; + public ref byte[] this[int index] => ref Buffers[index]; + + + public static KeyBatch Generate(int keyCount, KeyOrdering keyOrdering) + { + var buffers = new byte[keyCount][]; + + switch (keyOrdering) { + case KeyOrdering.Sequential: + PopulateSequential(buffers); + break; + + case KeyOrdering.Random: + PopulateRandom(buffers); + break; + + default: + throw new ArgumentException("That isn't a valid KeyOrdering", nameof(keyOrdering)); + } + + return new KeyBatch(buffers); + } + + private static void PopulateSequential(byte[][] buffers) + { + for (int i = 0; i < buffers.Length; i++) { + buffers[i] = CopyToArray(i); + } + } + + private static void PopulateRandom(byte[][] buffers) + { + var random = new Random(0); + var seen = new HashSet(buffers.Length); + + int i = 0; + while (i < buffers.Length) { + var keyValue = random.Next(0, buffers.Length); + + if (!seen.Add(keyValue)) + continue;//skip duplicates + + buffers[i++] = CopyToArray(keyValue); + } + } + + private static byte[] CopyToArray(int keyValue) + { + var key = new byte[4]; + MemoryMarshal.Write(key, ref keyValue); + return key; + } + } +} diff --git a/src/LightningDB.Benchmarks/Main.cs b/src/LightningDB.Benchmarks/Main.cs index 9c05a55..2c676e3 100644 --- a/src/LightningDB.Benchmarks/Main.cs +++ b/src/LightningDB.Benchmarks/Main.cs @@ -1,13 +1,13 @@ using System; using BenchmarkDotNet.Running; -using BenchmarkDotNet.Toolchains; namespace LightningDB.Benchmarks { public static class Entry { public static void Main(string[] args) { - BenchmarkRunner.Run(); + //BenchmarkRunner.Run(); + BenchmarkRunner.Run(); } } } \ No newline at end of file diff --git a/src/LightningDB.Benchmarks/ReadBenchmarks.cs b/src/LightningDB.Benchmarks/ReadBenchmarks.cs new file mode 100644 index 0000000..ded31e7 --- /dev/null +++ b/src/LightningDB.Benchmarks/ReadBenchmarks.cs @@ -0,0 +1,31 @@ + +using BenchmarkDotNet.Attributes; + +namespace LightningDB.Benchmarks +{ + [MemoryDiagnoser] + public class ReadBenchmarks : RWBenchmarksBase + { + public override void RunSetup() + { + base.RunSetup(); + + //setup data to read + using var tx = Env.BeginTransaction(); + for (int i = 0; i < KeyBuffers.Count; i++) + tx.Put(DB, KeyBuffers[i], ValueBuffer); + + tx.Commit(); + } + + [Benchmark] + public void Read() + { + using var transaction = Env.BeginTransaction(beginFlags: TransactionBeginFlags.ReadOnly); + + for (int i = 0; i < OpsPerTransaction; i++) { + var _ = transaction.Get(DB, KeyBuffers[i]); + } + } + } +} diff --git a/src/LightningDB.Benchmarks/WriteBenchmarks.cs b/src/LightningDB.Benchmarks/WriteBenchmarks.cs new file mode 100644 index 0000000..3c4bb09 --- /dev/null +++ b/src/LightningDB.Benchmarks/WriteBenchmarks.cs @@ -0,0 +1,24 @@ +using System.Collections; + +using BenchmarkDotNet.Attributes; + +using Microsoft.Diagnostics.Tracing.Parsers.MicrosoftWindowsTCPIP; + +namespace LightningDB.Benchmarks +{ + [MemoryDiagnoser] + public class WriteBenchmarks : RWBenchmarksBase + { + [Benchmark] + public void Write() + { + using var transaction = Env.BeginTransaction(); + + for (int i = 0; i < OpsPerTransaction; i++) { + transaction.Put(DB, KeyBuffers[i], ValueBuffer); + } + + transaction.Commit(); + } + } +}