mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-04-29 06:48:41 +00:00
Expanding test
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Esiur.Tests.Gvwie
|
||||||
|
{
|
||||||
|
public enum GeneratorPattern
|
||||||
|
{
|
||||||
|
Uniform,
|
||||||
|
Positive,
|
||||||
|
Negative,
|
||||||
|
Alternating,
|
||||||
|
Small,
|
||||||
|
Ascending,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,107 +8,142 @@ namespace Esiur.Tests.Gvwie;
|
|||||||
|
|
||||||
public static class IntArrayGenerator
|
public static class IntArrayGenerator
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static readonly Random rng = new Random(24241564);
|
private static readonly Random rng = new Random(24241564);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
public static long[] GenerateInt32Run(int length)
|
/// Generate an array composed of ascending runs (consecutive integers).
|
||||||
|
/// Example output: [1,2,3,4,5, 5001,5002,5003, 10000001,10000002,...]
|
||||||
|
/// Parameters:
|
||||||
|
/// - length: total array length
|
||||||
|
/// - minRunSize / maxRunSize: inclusive bounds for run lengths
|
||||||
|
/// - minValue / maxValue: allowed value range for run starts
|
||||||
|
/// - allowNegative: if false, generated values will be non-negative
|
||||||
|
/// - minGap / maxGap: approximate gap between runs (large gaps produce the jump examples)
|
||||||
|
/// </summary>
|
||||||
|
public static long[] GenerateRuns(int length,
|
||||||
|
int minRunSize = 3,
|
||||||
|
int maxRunSize = 8,
|
||||||
|
long minValue = -10_000_000L,
|
||||||
|
long maxValue = 10_000_000L,
|
||||||
|
bool allowNegative = true,
|
||||||
|
long minGap = 1_000L,
|
||||||
|
long maxGap = 10_000_000L)
|
||||||
{
|
{
|
||||||
|
if (length <= 0)
|
||||||
|
return Array.Empty<long>();
|
||||||
|
|
||||||
|
if (minRunSize < 1) minRunSize = 1;
|
||||||
|
if (maxRunSize < minRunSize) maxRunSize = minRunSize;
|
||||||
|
|
||||||
|
// If negative runs not allowed, clamp minValue to 0
|
||||||
|
if (!allowNegative && minValue < 0) minValue = 0;
|
||||||
|
|
||||||
var data = new long[length];
|
var data = new long[length];
|
||||||
|
int idx = 0;
|
||||||
|
long prevEnd = long.MinValue;
|
||||||
|
|
||||||
int i = 0;
|
while (idx < length)
|
||||||
var inSmallRange = true;
|
{
|
||||||
var inShortRange = false;
|
// choose run size
|
||||||
var inLargeRange = false;
|
int runSize = rng.Next(minRunSize, maxRunSize + 1);
|
||||||
var inLongRange = false;
|
if (idx + runSize > length)
|
||||||
|
runSize = length - idx;
|
||||||
|
|
||||||
long range = 30;
|
// pick a start. Aim for gaps between runs by either taking a random value
|
||||||
|
// or basing on previous end + gap. Try a few times to avoid accidental small gaps.
|
||||||
|
long start = 0;
|
||||||
|
long attemptUpper = maxValue - runSize; // inclusive exclusive handled by NextInt64
|
||||||
|
if (attemptUpper < minValue) attemptUpper = minValue;
|
||||||
|
|
||||||
while (i < length)
|
bool picked = false;
|
||||||
|
for (int attempt = 0; attempt < 10 && !picked; attempt++)
|
||||||
{
|
{
|
||||||
// stay same range
|
// decide whether to use a jump based on minGap/maxGap or pick random
|
||||||
if (rng.NextDouble() < 0.9)
|
if (prevEnd != long.MinValue && rng.NextDouble() < 0.7)
|
||||||
{
|
{
|
||||||
if (inSmallRange)
|
// generate a gap and place start after prevEnd + gap
|
||||||
data[i++] = rng.Next(-64, 65);
|
long gap = rng.NextInt64(minGap, Math.Max(minGap + 1, maxGap));
|
||||||
else if (inShortRange)
|
long candidate = prevEnd + gap;
|
||||||
data[i++] = rng.NextInt64(range - 100, range + 100);
|
// if candidate within allowed bounds adjust to fit
|
||||||
else if (inLargeRange)
|
if (candidate >= minValue && candidate <= attemptUpper)
|
||||||
data[i++] = rng.NextInt64(range - 1000, range + 1000);
|
|
||||||
else if (inLongRange)
|
|
||||||
data[i++] = rng.NextInt64(range - 10000, range + 10000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// switch range
|
start = candidate;
|
||||||
var rand = rng.NextDouble();
|
picked = true;
|
||||||
if (rand < 0.25)
|
break;
|
||||||
{
|
|
||||||
inSmallRange = true;
|
|
||||||
inShortRange = false;
|
|
||||||
inLargeRange = false;
|
|
||||||
inLongRange = false;
|
|
||||||
data[i++] = rng.Next(-64, 65);
|
|
||||||
}
|
|
||||||
else if (rand < 0.50)
|
|
||||||
{
|
|
||||||
inSmallRange = false;
|
|
||||||
inShortRange = true;
|
|
||||||
inLargeRange = false;
|
|
||||||
inLongRange = false;
|
|
||||||
range = rng.NextInt64(1000, short.MaxValue);
|
|
||||||
data[i++] = rng.NextInt64(range - 100, range + 100);
|
|
||||||
}
|
|
||||||
else if (rand < 0.75)
|
|
||||||
{
|
|
||||||
inSmallRange = false;
|
|
||||||
inShortRange = false;
|
|
||||||
inLargeRange = true;
|
|
||||||
inLongRange = false;
|
|
||||||
range = rng.NextInt64(1000, int.MaxValue);
|
|
||||||
data[i++] = rng.NextInt64(range - 1000, range + 1000);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
inSmallRange = false;
|
|
||||||
inShortRange = false;
|
|
||||||
inLargeRange = false;
|
|
||||||
inLongRange = true;
|
|
||||||
range = rng.NextInt64(10000, long.MaxValue);
|
|
||||||
data[i++] = rng.NextInt64(range - 10000, range + 10000);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// fallback: pick random start in allowed bounds
|
||||||
|
start = rng.NextInt64(minValue, attemptUpper + 1);
|
||||||
|
// avoid being too close to previous run end if present
|
||||||
|
if (prevEnd == long.MinValue || Math.Abs(start - prevEnd) >= minGap)
|
||||||
|
{
|
||||||
|
picked = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!picked)
|
||||||
|
{
|
||||||
|
// final fallback: clamp to bounds
|
||||||
|
start = Math.Max(minValue, Math.Min(attemptUpper, prevEnd + minGap));
|
||||||
|
}
|
||||||
|
|
||||||
|
// fill the run with consecutive values, careful with overflow
|
||||||
|
for (int j = 0; j < runSize; j++)
|
||||||
|
{
|
||||||
|
long val;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
checked
|
||||||
|
{
|
||||||
|
val = start + j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (OverflowException)
|
||||||
|
{
|
||||||
|
// clamp if overflow occurs
|
||||||
|
val = (start >= 0) ? long.MaxValue - (runSize - j - 1) : long.MinValue + (runSize - j - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
data[idx++] = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
prevEnd = data[idx - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Generate random int array of given length and distribution
|
// Generate random int array of given length and distribution
|
||||||
public static int[] GenerateInt32(int length, string pattern = "uniform",
|
public static int[] GenerateInt32(int length, GeneratorPattern pattern = GeneratorPattern.Uniform,
|
||||||
int range = int.MaxValue)
|
int range = int.MaxValue)
|
||||||
{
|
{
|
||||||
var data = new int[length];
|
var data = new int[length];
|
||||||
|
|
||||||
switch (pattern.ToLower())
|
switch (pattern)
|
||||||
{
|
{
|
||||||
case "uniform":
|
case GeneratorPattern.Uniform:
|
||||||
// Random values in [-range, range]
|
// Random values in [-range, range]
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = rng.Next(-range, range);
|
data[i] = rng.Next(-range, range);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "positive":
|
case GeneratorPattern.Positive:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = rng.Next(0, range);
|
data[i] = rng.Next(0, range);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "negative":
|
case GeneratorPattern.Negative:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = -rng.Next(0, range);
|
data[i] = -rng.Next(0, range);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "alternating":
|
case GeneratorPattern.Alternating:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
int val = rng.Next(0, range);
|
int val = rng.Next(0, range);
|
||||||
@@ -116,14 +151,14 @@ public static class IntArrayGenerator
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "small":
|
case GeneratorPattern.Small:
|
||||||
// Focused on small magnitudes to test ZigZag fast path
|
// Focused on small magnitudes to test ZigZag fast path
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = rng.Next(-64, 65);
|
data[i] = rng.Next(-64, 65);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "ascending":
|
case GeneratorPattern.Ascending:
|
||||||
{
|
{
|
||||||
int start = rng.Next(-range, range);
|
int start = rng.Next(-range, range);
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
@@ -247,30 +282,30 @@ public static class IntArrayGenerator
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate random int array of given length and distribution
|
// Generate random int array of given length and distribution
|
||||||
public static long[] GenerateInt64(int length, string pattern = "uniform",
|
public static long[] GenerateInt64(int length, GeneratorPattern pattern = GeneratorPattern.Uniform,
|
||||||
long range = long.MaxValue)
|
long range = long.MaxValue)
|
||||||
{
|
{
|
||||||
var data = new long[length];
|
var data = new long[length];
|
||||||
|
|
||||||
switch (pattern.ToLower())
|
switch (pattern)
|
||||||
{
|
{
|
||||||
case "uniform":
|
case GeneratorPattern.Uniform:
|
||||||
// Random values in [-range, range]
|
// Random values in [-range, range]
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = rng.NextInt64(-range, range);
|
data[i] = rng.NextInt64(-range, range);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "positive":
|
case GeneratorPattern.Positive:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = rng.NextInt64(0, range);
|
data[i] = rng.NextInt64(0, range);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "negative":
|
case GeneratorPattern.Negative:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = -rng.NextInt64(0, range);
|
data[i] = -rng.NextInt64(0, range);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "alternating":
|
case GeneratorPattern.Alternating:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
var val = rng.NextInt64(0, range);
|
var val = rng.NextInt64(0, range);
|
||||||
@@ -278,14 +313,14 @@ public static class IntArrayGenerator
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "small":
|
case GeneratorPattern.Small:
|
||||||
// Focused on small magnitudes to test ZigZag fast path
|
// Focused on small magnitudes to test ZigZag fast path
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = rng.NextInt64(-64, 65);
|
data[i] = rng.NextInt64(-64, 65);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "ascending":
|
case GeneratorPattern.Ascending:
|
||||||
{
|
{
|
||||||
var start = rng.NextInt64(-range, range);
|
var start = rng.NextInt64(-range, range);
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
@@ -300,29 +335,29 @@ public static class IntArrayGenerator
|
|||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static short[] GenerateInt16(int length, string pattern = "uniform",
|
public static short[] GenerateInt16(int length, GeneratorPattern pattern = GeneratorPattern.Uniform,
|
||||||
short range = short.MaxValue)
|
short range = short.MaxValue)
|
||||||
{
|
{
|
||||||
var data = new short[length];
|
var data = new short[length];
|
||||||
|
|
||||||
switch (pattern.ToLower())
|
switch (pattern)
|
||||||
{
|
{
|
||||||
case "uniform":
|
case GeneratorPattern.Uniform:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = (short)rng.Next(-range, range + 1);
|
data[i] = (short)rng.Next(-range, range + 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "positive":
|
case GeneratorPattern.Positive:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = (short)rng.Next(0, range + 1);
|
data[i] = (short)rng.Next(0, range + 1);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "negative":
|
case GeneratorPattern.Negative:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = (short)(-rng.Next(0, range + 1));
|
data[i] = (short)(-rng.Next(0, range + 1));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "alternating":
|
case GeneratorPattern.Alternating:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
{
|
{
|
||||||
short val = (short)rng.Next(0, range + 1);
|
short val = (short)rng.Next(0, range + 1);
|
||||||
@@ -330,13 +365,13 @@ public static class IntArrayGenerator
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "small":
|
case GeneratorPattern.Small:
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
data[i] = (short)rng.Next(-64, 65);
|
data[i] = (short)rng.Next(-64, 65);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
|
||||||
case "ascending":
|
case GeneratorPattern.Ascending:
|
||||||
{
|
{
|
||||||
short start = (short)rng.Next(-range, range);
|
short start = (short)rng.Next(-range, range);
|
||||||
for (int i = 0; i < length; i++)
|
for (int i = 0; i < length; i++)
|
||||||
|
|||||||
@@ -21,71 +21,151 @@ namespace Esiur.Tests.Gvwie
|
|||||||
public virtual IList<T>? Values { get; set; }
|
public virtual IList<T>? Values { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
internal class IntArrayRunner
|
internal class IntArrayRunner
|
||||||
{
|
{
|
||||||
public void Run()
|
public void Run()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
const int TEST_ITERATIONS = 100;
|
||||||
|
const int SAMPLE_SIZE = 100;
|
||||||
|
|
||||||
Console.WriteLine(";Esiur;FlatBuffer;ProtoBuffer;MessagePack;BSON;CBOR;Avro,Optimal");
|
Console.WriteLine(";Esiur;FlatBuffer;ProtoBuffer;MessagePack;BSON;CBOR;Avro,Optimal");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Console.Write("Cluster (Int32);");
|
Console.Write("Cluster (Int32);");
|
||||||
////CompareInt(int32cluster);
|
|
||||||
//Average(() => CompareInt(IntArrayGenerator.GenerateInt32Run(1000)), 1000);
|
|
||||||
|
|
||||||
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateRuns(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Positive (Int32);");
|
Console.Write("Positive (Int32);");
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(1000, "positive")), 1000);
|
|
||||||
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(SAMPLE_SIZE, GeneratorPattern.Uniform)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Negative (Int32);");
|
Console.Write("Negative (Int32);");
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(1000, "negative")), 1000);
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(SAMPLE_SIZE, GeneratorPattern.Negative)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Small (Int32);");
|
Console.Write("Small (Int32);");
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(1000, "small")), 1000);
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(SAMPLE_SIZE, GeneratorPattern.Small)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
// CompareInt(int32small);
|
// CompareInt(int32small);
|
||||||
|
|
||||||
Console.Write("Alternating (Int32);");
|
Console.Write("Alternating (Int32);");
|
||||||
//CompareInt(int32alter);
|
//CompareInt(int32alter);
|
||||||
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(1000, "alternating")), 1000);
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(SAMPLE_SIZE, GeneratorPattern.Alternating)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Ascending (Int32);");
|
Console.Write("Ascending (Int32);");
|
||||||
//CompareInt(int32asc);
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(1000, "ascending")), 1000);
|
|
||||||
|
|
||||||
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(SAMPLE_SIZE, GeneratorPattern.Ascending)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Int64;");
|
Console.Write("Int64;");
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt64(1000, "uniform")), 1000);
|
|
||||||
//CompareInt(int64Uni);
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt64(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Int32;");
|
Console.Write("Int32;");
|
||||||
//CompareInt(int32Uni);
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(1000, "uniform")), 1000);
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt32(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("Int16;");
|
Console.Write("Int16;");
|
||||||
//CompareInt(int16Uni);
|
|
||||||
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateInt16(1000, "uniform")), 1000);
|
|
||||||
|
|
||||||
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateInt16(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("UInt64;");
|
Console.Write("UInt64;");
|
||||||
//CompareInt(uint64Uni);
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateUInt64(1000, "uniform")), 1000);
|
|
||||||
|
|
||||||
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateUInt64(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("UInt32;");
|
Console.Write("UInt32;");
|
||||||
//CompareInt(uint32Uni);
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateUInt32(1000, "uniform")), 1000);
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateUInt32(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
|
|
||||||
Console.Write("UInt16;");
|
Console.Write("UInt16;");
|
||||||
//CompareInt(uint16Uni);
|
|
||||||
Average(() => CompareInt(IntArrayGenerator.GenerateUInt16(1000, "uniform")), 1000);
|
|
||||||
|
|
||||||
|
PrintAverage(
|
||||||
|
Average(() => CompareInt(IntArrayGenerator.GenerateUInt16(SAMPLE_SIZE)), TEST_ITERATIONS)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Generate CSV suitable for Office Word chart where the sample size varies.
|
||||||
|
// Produces a CSV with header: SampleSize;Esiur;FlatBuffer;ProtoBuffer;MessagePack;BSON;CBOR;Avro;Optimal
|
||||||
|
public void RunChart()
|
||||||
|
{
|
||||||
|
var sizes = new int[] { 10, 100, 1000, 10000, 100000 };
|
||||||
|
|
||||||
|
// Define generators to evaluate. Each entry maps a name to a function that
|
||||||
|
// given a sample size returns the averages (double[]) by calling Average(...).
|
||||||
|
var generators = new List<(string name, Func<int, int, double[]> fn)>()
|
||||||
|
{
|
||||||
|
("GenerateRuns", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateRuns(size)), iterations)),
|
||||||
|
("Int32_Uniform", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt32(size, GeneratorPattern.Uniform)), iterations)),
|
||||||
|
("Int32_Negative", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt32(size, GeneratorPattern.Negative)), iterations)),
|
||||||
|
("Int32_Small", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt32(size, GeneratorPattern.Small)), iterations)),
|
||||||
|
("Int32_Alternating", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt32(size, GeneratorPattern.Alternating)), iterations)),
|
||||||
|
("Int32_Ascending", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt32(size, GeneratorPattern.Ascending)), iterations)),
|
||||||
|
("Int64", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt64(size)), iterations)),
|
||||||
|
("Int32_Default", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt32(size)), iterations)),
|
||||||
|
("Int16", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateInt16(size)), iterations)),
|
||||||
|
("UInt64", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateUInt64(size)), iterations)),
|
||||||
|
("UInt32", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateUInt32(size)), iterations)),
|
||||||
|
("UInt16", (size, iterations) => Average(() => CompareInt(IntArrayGenerator.GenerateUInt16(size)), iterations)),
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var gen in generators)
|
||||||
|
{
|
||||||
|
var sb = new System.Text.StringBuilder();
|
||||||
|
sb.AppendLine("SampleSize;Esiur;FlatBuffer;ProtoBuffer;MessagePack;BSON;CBOR;Avro;Optimal");
|
||||||
|
|
||||||
|
foreach (var size in sizes)
|
||||||
|
{
|
||||||
|
// Choose iterations depending on size to keep total runtime reasonable
|
||||||
|
int iterations;
|
||||||
|
if (size <= 100) iterations = 1000;
|
||||||
|
else if (size <= 1000) iterations = 200;
|
||||||
|
else if (size <= 10000) iterations = 50;
|
||||||
|
else iterations = 10;
|
||||||
|
|
||||||
|
Console.WriteLine($"Running {gen.name} sample size={size}, iterations={iterations}...");
|
||||||
|
|
||||||
|
var averages = gen.fn(size, iterations);
|
||||||
|
|
||||||
|
sb.Append(size);
|
||||||
|
for (int i = 0; i < averages.Length; i++)
|
||||||
|
{
|
||||||
|
sb.Append(';');
|
||||||
|
sb.Append(Math.Round(averages[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.AppendLine();
|
||||||
|
}
|
||||||
|
|
||||||
|
var file = $"run_chart_{gen.name}.csv";
|
||||||
|
System.IO.File.WriteAllText(file, sb.ToString());
|
||||||
|
Console.WriteLine($"Chart CSV written to: {file}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public static (int, int, int, int, int, int, int, int) CompareInt(long[] sample)
|
public static (int, int, int, int, int, int, int, int) CompareInt(long[] sample)
|
||||||
{
|
{
|
||||||
var intRoot = new ArrayRoot<long>() { Values = sample };
|
var intRoot = new ArrayRoot<long>() { Values = sample };
|
||||||
@@ -300,7 +380,7 @@ namespace Esiur.Tests.Gvwie
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static (double, double, double, double, double, double, double, double) Average(Func<(int, int, int, int, int, int, int, int)> call, int count)
|
static double[] Average(Func<(int, int, int, int, int, int, int, int)> call, int count)
|
||||||
{
|
{
|
||||||
var sum = new List<(int, int, int, int, int, int, int, int)>();
|
var sum = new List<(int, int, int, int, int, int, int, int)>();
|
||||||
|
|
||||||
@@ -308,7 +388,7 @@ namespace Esiur.Tests.Gvwie
|
|||||||
sum.Add(call());
|
sum.Add(call());
|
||||||
|
|
||||||
|
|
||||||
var rt = (sum.Average(x => x.Item1),
|
var rt = new double[]{ sum.Average(x => x.Item1),
|
||||||
sum.Average(x => x.Item2),
|
sum.Average(x => x.Item2),
|
||||||
sum.Average(x => x.Item3),
|
sum.Average(x => x.Item3),
|
||||||
sum.Average(x => x.Item4),
|
sum.Average(x => x.Item4),
|
||||||
@@ -316,13 +396,36 @@ namespace Esiur.Tests.Gvwie
|
|||||||
sum.Average(x => x.Item6),
|
sum.Average(x => x.Item6),
|
||||||
sum.Average(x => x.Item7),
|
sum.Average(x => x.Item7),
|
||||||
sum.Average(x => x.Item8)
|
sum.Average(x => x.Item8)
|
||||||
);
|
};
|
||||||
|
|
||||||
|
Console.WriteLine($"{rt[0]};{rt[1]};{rt[2]};{rt[3]};{rt[4]};{rt[5]};{rt[6]};{rt[7]}");
|
||||||
|
|
||||||
Console.WriteLine($"{rt.Item1};{rt.Item2};{rt.Item3};{rt.Item4};{rt.Item5};{rt.Item6};{rt.Item7};{rt.Item8}");
|
|
||||||
|
|
||||||
return rt;
|
return rt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static string PrintAverage(double[] values)
|
||||||
|
{
|
||||||
|
// Determine winner (lowest average size)
|
||||||
|
var names = new string[] { "Esiur", "FlatBuffer", "ProtoBuffer", "MessagePack", "BSON", "CBOR", "Avro", "Optimal" };
|
||||||
|
var min = values.SkipLast(1).Min();
|
||||||
|
var idx = Array.IndexOf(values, min);
|
||||||
|
if (idx >= 0 && idx < names.Length)
|
||||||
|
{
|
||||||
|
if (idx == 0)
|
||||||
|
|
||||||
|
Console.ForegroundColor = ConsoleColor.Green;
|
||||||
|
else
|
||||||
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
|
|
||||||
|
Console.WriteLine($"Winner: {names[idx]} ({min:F0})");
|
||||||
|
Console.ForegroundColor = ConsoleColor.White;
|
||||||
|
|
||||||
|
return names[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
public static byte[] SerializeFlatBuffers<T>(ArrayRoot<T> array)
|
public static byte[] SerializeFlatBuffers<T>(ArrayRoot<T> array)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,4 +11,5 @@ MessagePack.MessagePackSerializer.DefaultOptions = MessagePackSerializerOptions.
|
|||||||
|
|
||||||
var ints = new IntArrayRunner();
|
var ints = new IntArrayRunner();
|
||||||
ints.Run();
|
ints.Run();
|
||||||
|
ints.RunChart();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user