Created
October 22, 2019 05:14
-
-
Save ociaw/b25241aa89c9428c02576c9587042595 to your computer and use it in GitHub Desktop.
A crappy struct benchmark
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* A quick and dirty micro benchmark on passing a class vs a struct vs a struct by reference | |
* | |
* This is not necessarily a good benchmark. The code will likely perform much differently | |
* under a more realistic scenario. | |
* | |
* Summary: | |
* | Method | N | Mean | Error | StdDev | Rank | | |
* |------------------------------ |-------- |------------------:|--------------:|--------------:|-----:| | |
* | BenchmarkMediumClass | 1 | 0.6700 ns | 0.0017 ns | 0.0016 ns | 2 | | |
* | BenchmarkMediumStruct | 1 | 0.5522 ns | 0.0025 ns | 0.0023 ns | 1 | | |
* | BenchmarkMediumStructByRef | 1 | 0.5519 ns | 0.0034 ns | 0.0030 ns | 1 | | |
* | BenchmarkLargeClass | 1 | 1.6638 ns | 0.0036 ns | 0.0032 ns | 3 | | |
* | BenchmarkLargeStruct | 1 | 1.9873 ns | 0.0034 ns | 0.0030 ns | 5 | | |
* | BenchmarkLargeStructByRef | 1 | 1.7395 ns | 0.0036 ns | 0.0033 ns | 4 | | |
* | BenchmarkVeryLargeClass | 1 | 2.3446 ns | 0.0085 ns | 0.0080 ns | 6 | | |
* | BenchmarkVeryLargeStruct | 1 | 3.2282 ns | 0.0086 ns | 0.0081 ns | 8 | | |
* | BenchmarkVeryLargeStructByRef | 1 | 2.5289 ns | 0.0061 ns | 0.0057 ns | 7 | | |
* | BenchmarkMediumClass | 100 | 68.7325 ns | 0.1097 ns | 0.1026 ns | 9 | | |
* | BenchmarkMediumStruct | 100 | 69.0129 ns | 0.1152 ns | 0.1078 ns | 9 | | |
* | BenchmarkMediumStructByRef | 100 | 68.9675 ns | 0.1908 ns | 0.1785 ns | 9 | | |
* | BenchmarkLargeClass | 100 | 117.6015 ns | 0.1037 ns | 0.0970 ns | 10 | | |
* | BenchmarkLargeStruct | 100 | 168.3852 ns | 0.3010 ns | 0.2815 ns | 13 | | |
* | BenchmarkLargeStructByRef | 100 | 134.6392 ns | 0.1441 ns | 0.1348 ns | 11 | | |
* | BenchmarkVeryLargeClass | 100 | 179.4940 ns | 0.1901 ns | 0.1778 ns | 14 | | |
* | BenchmarkVeryLargeStruct | 100 | 248.8764 ns | 0.6929 ns | 0.6481 ns | 15 | | |
* | BenchmarkVeryLargeStructByRef | 100 | 147.1239 ns | 0.2157 ns | 0.2018 ns | 12 | | |
* | BenchmarkMediumClass | 10000 | 6,486.7953 ns | 7.0721 ns | 6.6152 ns | 16 | | |
* | BenchmarkMediumStruct | 10000 | 6,484.1350 ns | 12.9782 ns | 12.1398 ns | 16 | | |
* | BenchmarkMediumStructByRef | 10000 | 6,483.1949 ns | 22.7971 ns | 21.3244 ns | 16 | | |
* | BenchmarkLargeClass | 10000 | 11,183.8714 ns | 12.2654 ns | 11.4731 ns | 17 | | |
* | BenchmarkLargeStruct | 10000 | 16,766.1190 ns | 32.2947 ns | 30.2085 ns | 20 | | |
* | BenchmarkLargeStructByRef | 10000 | 12,950.8779 ns | 20.5533 ns | 19.2256 ns | 18 | | |
* | BenchmarkVeryLargeClass | 10000 | 17,282.3985 ns | 19.3402 ns | 18.0908 ns | 21 | | |
* | BenchmarkVeryLargeStruct | 10000 | 24,676.5957 ns | 30.6337 ns | 28.6547 ns | 22 | | |
* | BenchmarkVeryLargeStructByRef | 10000 | 14,191.3848 ns | 23.9293 ns | 22.3835 ns | 19 | | |
* | BenchmarkMediumClass | 1000000 | 658,091.9713 ns | 781.5372 ns | 692.8124 ns | 23 | | |
* | BenchmarkMediumStruct | 1000000 | 659,450.6557 ns | 777.0098 ns | 688.7989 ns | 23 | | |
* | BenchmarkMediumStructByRef | 1000000 | 658,683.6163 ns | 914.4711 ns | 763.6248 ns | 23 | | |
* | BenchmarkLargeClass | 1000000 | 1,132,105.6250 ns | 643.7651 ns | 602.1782 ns | 24 | | |
* | BenchmarkLargeStruct | 1000000 | 1,712,619.0104 ns | 2,524.8616 ns | 2,361.7571 ns | 27 | | |
* | BenchmarkLargeStructByRef | 1000000 | 1,552,783.2682 ns | 3,965.1857 ns | 3,709.0371 ns | 26 | | |
* | BenchmarkVeryLargeClass | 1000000 | 1,736,865.7506 ns | 1,658.1848 ns | 1,469.9376 ns | 28 | | |
* | BenchmarkVeryLargeStruct | 1000000 | 2,480,650.8650 ns | 3,665.8116 ns | 3,249.6465 ns | 29 | | |
* | BenchmarkVeryLargeStructByRef | 1000000 | 1,431,716.5179 ns | 2,365.8831 ns | 2,097.2937 ns | 25 | | |
* | |
*/ | |
using System; | |
using BenchmarkDotNet.Attributes; | |
using BenchmarkDotNet.Running; | |
namespace StructBenchmarking | |
{ | |
public class Program | |
{ | |
public static void Main() | |
{ | |
var summary = BenchmarkRunner.Run<Benchmark>(); | |
} | |
} | |
[RPlotExporter, RankColumn] | |
public class Benchmark | |
{ | |
private MediumClass _mediumClass; | |
private MediumStruct _mediumStruct; | |
private LargeClass _largeClass; | |
private LargeStruct _largeStruct; | |
private VeryLargeClass _veryLargeClass; | |
private VeryLargeStruct _veryLargeStruct; | |
private long[] _data; | |
[Params(1, 100, 10000, 1000000)] | |
public int N; | |
[GlobalSetup] | |
public void Setup() | |
{ | |
const Int32 seed = 42; | |
var rand = new Random(seed); | |
_data = new long[N]; | |
long a = rand.Next(); | |
long b = rand.Next(); | |
long c = rand.Next(); | |
long d = rand.Next(); | |
long v = rand.Next(); | |
long x = rand.Next(); | |
long y = rand.Next(); | |
long z = rand.Next(); | |
_mediumClass = new MediumClass(v, x); | |
_mediumStruct = new MediumStruct(v, x); | |
_largeClass = new LargeClass(v, x, y, z); | |
_largeStruct = new LargeStruct(v, x, y, z); | |
_veryLargeClass = new VeryLargeClass(a, b, c, d, v, x, y, z); | |
_veryLargeStruct = new VeryLargeStruct(a, b, c, d, v, x, y, z); | |
for (int i = 0; i < N; i++) | |
{ | |
long r = rand.Next(); | |
_data[i] = r; | |
} | |
} | |
[Benchmark] | |
public long BenchmarkMediumClass() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumClass(_mediumClass); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkMediumStruct() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumStruct(_mediumStruct); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkMediumStructByRef() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumStructByRef(_mediumStruct); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkLargeClass() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumClass(_largeClass); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkLargeStruct() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumStruct(_largeStruct); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkLargeStructByRef() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumStructByRef(_largeStruct); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkVeryLargeClass() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumClass(_veryLargeClass); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkVeryLargeStruct() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumStruct(_veryLargeStruct); | |
return sum; | |
} | |
[Benchmark] | |
public long BenchmarkVeryLargeStructByRef() | |
{ | |
long sum = 0; | |
for (int i = 0; i < N; i++) | |
sum += _data[i] + SumStructByRef(_veryLargeStruct); | |
return sum; | |
} | |
private long SumClass(MediumClass value) => value.V + value.X; | |
private long SumStruct(MediumStruct value) => value.V + value.X; | |
private long SumStructByRef(MediumStruct value) => value.V + value.X; | |
private long SumClass(LargeClass value) => value.V + value.X + value.Y + value.Z; | |
private long SumStruct(LargeStruct value) => value.V + value.X + value.Y + value.Z; | |
private long SumStructByRef(in LargeStruct value) => value.V + value.X + value.Y + value.Z; | |
private long SumClass(VeryLargeClass value) => value.A + value.B + value.C + value.D + value.V + value.X + value.Y + value.Z; | |
private long SumStruct(VeryLargeStruct value) => value.A + value.B + value.C + value.D + value.V + value.X + value.Y + value.Z; | |
private long SumStructByRef(in VeryLargeStruct value) => value.A + value.B + value.C + value.D + value.V + value.X + value.Y + value.Z; | |
} | |
public sealed class MediumClass | |
{ | |
public MediumClass(long v, long x) | |
{ | |
V = v; | |
X = x; | |
} | |
public long V { get; } | |
public long X { get; } | |
} | |
public readonly struct MediumStruct | |
{ | |
public MediumStruct(long v, long x) | |
{ | |
V = v; | |
X = x; | |
} | |
public long V { get; } | |
public long X { get; } | |
} | |
public sealed class LargeClass | |
{ | |
public LargeClass(long v, long x, long y, long z) | |
{ | |
V = v; | |
X = x; | |
Y = y; | |
Z = z; | |
} | |
public long V { get; } | |
public long X { get; } | |
public long Y { get; } | |
public long Z { get; } | |
} | |
public readonly struct LargeStruct | |
{ | |
public LargeStruct(long v, long x, long y, long z) | |
{ | |
V = v; | |
X = x; | |
Y = y; | |
Z = z; | |
} | |
public long V { get; } | |
public long X { get; } | |
public long Y { get; } | |
public long Z { get; } | |
} | |
public sealed class VeryLargeClass | |
{ | |
public VeryLargeClass(long a, long b, long c, long d, long v, long x, long y, long z) | |
{ | |
A = a; | |
B = b; | |
C = c; | |
D = d; | |
V = v; | |
X = x; | |
Y = y; | |
Z = z; | |
} | |
public long A { get; } | |
public long B { get; } | |
public long C { get; } | |
public long D { get; } | |
public long V { get; } | |
public long X { get; } | |
public long Y { get; } | |
public long Z { get; } | |
} | |
public readonly struct VeryLargeStruct | |
{ | |
public VeryLargeStruct(long a, long b, long c, long d, long v, long x, long y, long z) | |
{ | |
A = a; | |
B = b; | |
C = c; | |
D = d; | |
V = v; | |
X = x; | |
Y = y; | |
Z = z; | |
} | |
public long A { get; } | |
public long B { get; } | |
public long C { get; } | |
public long D { get; } | |
public long V { get; } | |
public long X { get; } | |
public long Y { get; } | |
public long Z { get; } | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Project Sdk="Microsoft.NET.Sdk"> | |
<PropertyGroup> | |
<OutputType>Exe</OutputType> | |
<TargetFramework>netcoreapp3.0</TargetFramework> | |
</PropertyGroup> | |
<ItemGroup> | |
<PackageReference Include="BenchmarkDotNet" Version="0.11.5" /> | |
</ItemGroup> | |
</Project> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment