Skip to content

Instantly share code, notes, and snippets.

@bellons91
Created May 13, 2022 09:22
Show Gist options
  • Save bellons91/938f257d95ac8abfd9aa4194b7140df3 to your computer and use it in GitHub Desktop.
Save bellons91/938f257d95ac8abfd9aa4194b7140df3 to your computer and use it in GitHub Desktop.
This benchmark shows the performance of using Structs passed by reference vs using Classes

BenchmarkDotNet=v0.13.1, OS=Windows 10.0.18363.1500 (1909/November2019Update/19H2) Intel Core i7-8550U CPU 1.80GHz (Kaby Lake R), 1 CPU, 8 logical and 4 physical cores .NET SDK=6.0.202 [Host] : .NET 5.0.16 (5.0.1622.16705), X64 RyuJIT

Method Size Mean Error StdDev Median Gen 0 Allocated
RunClass 10 204.9 ns 3.77 ns 6.81 ns 203.4 ns 0.0899 376 B
RunStructNoRef 10 138.7 ns 2.57 ns 2.28 ns 138.7 ns 0.0229 96 B
RunStructRef 10 149.0 ns 3.30 ns 9.31 ns 146.9 ns 0.0229 96 B
RunClass 100 2,080.2 ns 88.92 ns 255.14 ns 1,977.7 ns 0.7782 3,256 B
RunStructNoRef 100 1,211.4 ns 23.33 ns 31.14 ns 1,205.0 ns 0.1087 456 B
RunStructRef 100 1,237.6 ns 23.71 ns 24.35 ns 1,230.8 ns 0.1087 456 B
RunClass 1000 18,751.2 ns 234.45 ns 207.83 ns 18,753.1 ns 7.6599 32,056 B
RunStructNoRef 1000 11,836.6 ns 228.92 ns 224.83 ns 11,771.1 ns 0.9613 4,056 B
RunStructRef 1000 11,961.8 ns 231.53 ns 193.34 ns 11,898.2 ns 0.9613 4,056 B

// * Legends * Size : Value of the 'Size' parameter Mean : Arithmetic mean of all measurements Error : Half of 99.9% confidence interval StdDev : Standard deviation of all measurements Median : Value separating the higher half of all measurements (50th percentile) Gen 0 : GC Generation 0 collects per 1000 operations Allocated : Allocated memory per single operation (managed only, inclusive, 1KB = 1024B) 1 ns : 1 Nanosecond (0.000000001 sec)

// * Diagnostic Output - MemoryDiagnoser *

// ***** BenchmarkRunner: End ***** // ** Remained 0 benchmark(s) to run ** Run time: 00:05:15 (315.08 sec), executed benchmarks: 9

Global total time: 00:05:15 (315.09 sec), executed benchmarks: 9 // * Artifacts cleanup *

#LINQPad optimize+
void Main()
{
var summary = BenchmarkRunner.Run<HashSetPerformance>();
}
[MemoryDiagnoser]
public class HashSetPerformance
{
[Params(10,100,1000)]
public int Size;
Random rd;
public HashSetPerformance()
{
this.rd = new Random();
}
[Benchmark]
public void RunClass()
{
List<AsClass> items = new List<AsClass>(Size);
//create
for (int i = 0; i < Size; i++)
{
items.Add(new AsClass
{
MyProperty = rd.Next()
});
}
//access
for (int i = 0; i < items.Count; i++)
{
var element = items[i];
DoClass(element);
}
}
[Benchmark]
public void RunStructNoRef()
{
List<AsStruct> items = new List<AsStruct>(Size);
//create
for (int i = 0; i < Size; i++)
{
items.Add(new AsStruct
{
MyProperty = rd.Next()
});
}
//access
for (int i = 0; i < items.Count; i++)
{
var element = items[i];
DoNoRef(element);
}
}
[Benchmark]
public void RunStructRef()
{
List<AsStruct> items = new List<AsStruct>(Size);
//create
for (int i = 0; i < Size; i++)
{
items.Add(new AsStruct
{
MyProperty = rd.Next()
});
}
//access
for (int i = 0; i < items.Count; i++)
{
var element = items[i];
DoRef(ref element);
}
}
public void DoRef(ref AsStruct s)
{
s.MyProperty = 29;
}
public void DoNoRef(AsStruct s)
{
s.MyProperty = 29;
}
public void DoClass(AsClass c)
{
c.MyProperty = 29;
}
public class AsClass
{
public int MyProperty { get; set; }
}
public struct AsStruct
{
public int MyProperty { get; set; }
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment