-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
3d21804
commit f55f176
Showing
8 changed files
with
413 additions
and
1 deletion.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
using System.Runtime.InteropServices; | ||
|
||
namespace Benchmarks.BestPractices; | ||
|
||
/* | ||
| Method | Runtime | Mean | Error | StdDev | Ratio | Allocated | | ||
|------------ |--------- |---------:|--------:|--------:|---------:|----------:|- | ||
| Get | .NET 6.0 | 708.6 ns | 2.23 ns | 1.74 ns | baseline | - | | ||
| UnsafeGet | .NET 6.0 | 940.6 ns | 3.42 ns | 3.20 ns | +33% | - | | ||
| SpanGet | .NET 6.0 | 432.0 ns | 5.55 ns | 5.19 ns | -39% | - | | ||
| SpanListGet | .NET 6.0 | 426.9 ns | 1.05 ns | 0.93 ns | -40% | - | | ||
| GetReverse | .NET 6.0 | 709.4 ns | 3.26 ns | 2.72 ns | +0% | - | | ||
| | | | | | | | | ||
| Get | .NET 8.0 | 477.2 ns | 7.30 ns | 6.47 ns | baseline | - | | ||
| UnsafeGet | .NET 8.0 | 427.1 ns | 0.80 ns | 0.62 ns | -11% | - | | ||
| SpanGet | .NET 8.0 | 297.4 ns | 2.26 ns | 1.89 ns | -38% | - | | ||
| SpanListGet | .NET 8.0 | 299.0 ns | 3.41 ns | 3.02 ns | -37% | - | | ||
| GetReverse | .NET 8.0 | 355.5 ns | 1.50 ns | 1.25 ns | -26% | - | | ||
*/ | ||
public class BoundsCheck | ||
{ | ||
private const int SIZE = 1000; | ||
private static readonly int[] _array = Enumerable.Range(0, SIZE).ToArray(); | ||
private static readonly List<int> _list = Enumerable.Range(0, SIZE).ToList(); | ||
|
||
[Benchmark(Baseline = true)] | ||
public int Get() | ||
{ | ||
int x = 0; | ||
for (int i = 0; i < SIZE; i++) | ||
{ | ||
x = _array[i]; | ||
} | ||
return x; | ||
} | ||
|
||
[Benchmark] | ||
public int UnsafeGet() | ||
{ | ||
int x = 0; | ||
for (int i = 0; i < SIZE; i++) | ||
{ | ||
x = Unsafe.Add(ref MemoryMarshal.GetArrayDataReference(_array), i); | ||
} | ||
return x; | ||
} | ||
|
||
[Benchmark] | ||
public int SpanGet() | ||
{ | ||
var span = _array.AsSpan(); | ||
int x = 0; | ||
for (int i = 0; i < SIZE; i++) | ||
{ | ||
x = span[i]; | ||
} | ||
return x; | ||
} | ||
|
||
[Benchmark] | ||
public int SpanListGet() | ||
{ | ||
var span = CollectionsMarshal.AsSpan(_list); | ||
int x = 0; | ||
for (int i = 0; i < SIZE; i++) | ||
{ | ||
x = span[i]; | ||
} | ||
return x; | ||
} | ||
|
||
[Benchmark] | ||
public int GetReverse() | ||
{ | ||
int x = 0; | ||
for (int i = SIZE - 1; i >= 0; i--) | ||
{ | ||
x = _array[i]; | ||
} | ||
|
||
return x; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
namespace Benchmarks.BestPractices; | ||
|
||
/* | ||
| Method | Runtime | Mean | Error | StdDev | Ratio | Gen0 | Allocated | | ||
|------- |--------- |-----------:|---------:|----------:|---------:|-------:|----------:| | ||
| Boxing | .NET 6.0 | 2,881.4 ns | 55.29 ns | 71.89 ns | baseline | 3.8261 | 24024 B | | ||
| Int | .NET 6.0 | 244.8 ns | 3.10 ns | 2.75 ns | -92% | 0.0038 | 24 B | | ||
| | | | | | | | | | ||
| Boxing | .NET 8.0 | 2,946.5 ns | 56.35 ns | 155.20 ns | baseline | 3.8261 | 24024 B | | ||
| Int | .NET 8.0 | 248.8 ns | 4.66 ns | 4.13 ns | -92% | 0.0038 | 24 B | | ||
*/ | ||
public class BoxingBench | ||
{ | ||
private const int SIZE = 1000; | ||
|
||
[Benchmark(Baseline = true)] | ||
public object Boxing() | ||
{ | ||
int x = 0; | ||
object obj = x; | ||
for (int i = 0; i < SIZE; i++) | ||
{ | ||
x++; | ||
obj = x; | ||
} | ||
return obj; | ||
} | ||
|
||
|
||
[Benchmark] | ||
public object Int() | ||
{ | ||
int x = 0; | ||
object obj = x; | ||
for (int i = 0; i < SIZE; i++) | ||
{ | ||
x++; | ||
} | ||
return obj; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
namespace Benchmarks.BestPractices; | ||
|
||
/* | ||
| Method | Runtime | Mean | Error | StdDev | Ratio | Gen0 | Allocated | | ||
|--------------- |--------- |---------:|----------:|----------:|---------:|-------:|----------:|- | ||
| UnBoxing | .NET 6.0 | 2.931 us | 0.0568 us | 0.0584 us | baseline | 3.8261 | 24024 B | | ||
| UnBoxingUnsafe | .NET 6.0 | 1.248 us | 0.0046 us | 0.0041 us | -57% | 0.0038 | 24 B | | ||
| | | | | | | | | | ||
| UnBoxing | .NET 8.0 | 2.961 us | 0.0547 us | 0.0427 us | baseline | 3.8261 | 24024 B | | ||
| UnBoxingUnsafe | .NET 8.0 | 1.236 us | 0.0235 us | 0.0289 us | -58% | 0.0038 | 24 B | | ||
*/ | ||
public class BoxingUnsafe | ||
{ | ||
private const int SIZE = 1000; | ||
|
||
[Benchmark(Baseline = true)] | ||
public object UnBoxing() | ||
{ | ||
object obj = 0; | ||
for (int i = 0; i < SIZE; i++) | ||
Inc((int)obj); | ||
|
||
return obj; | ||
|
||
static object Inc(int x) => ++x; | ||
} | ||
|
||
|
||
[Benchmark] | ||
public object UnBoxingUnsafe() | ||
{ | ||
object obj = 0; | ||
for (int i = 0; i < SIZE; i++) | ||
Unsafe.Unbox<int>(obj)++; | ||
|
||
return obj; | ||
} | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
namespace Benchmarks.BestPractices; | ||
internal class CodeGen | ||
{ | ||
static bool IsEven(int i) => (i % 2) == 0; | ||
} | ||
|
||
|
||
/* | ||
mono: | ||
Program:IsEven(System.Int32):System.Boolean: | ||
sub rsp, 8 | ||
mov [rsp], r15 | ||
mov r15, rdi | ||
mov rcx, r15 | ||
shr ecx, 1Fh | ||
mov rax, r15 | ||
add eax, ecx | ||
and rax, 1 | ||
sub eax, ecx | ||
test eax, eax | ||
sete al | ||
movzx rax, al | ||
mov r15, [rsp] | ||
add rsp, 8 | ||
ret | ||
6.0 | ||
Program:IsEven(int):bool: | ||
test dil, 1 | ||
sete al | ||
movzx rax, al | ||
ret | ||
8.0 | ||
Program:IsEven(int):bool (FullOpts): | ||
G_M20272_IG01: ;; offset=0x0000 | ||
G_M20272_IG02: ;; offset=0x0000 | ||
mov eax, edi | ||
not eax | ||
and eax, 1 | ||
G_M20272_IG03: ;; offset=0x0007 | ||
ret | ||
*/ |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
[Start](https://benchmarkdotnet.org/) | ||
[Getting Started Guide](https://benchmarkdotnet.org/articles/guides/getting-started.html) | ||
[Main Features List](https://benchmarkdotnet.org/#main-features) | ||
|
||
|
||
|
||
# Running | ||
[Config](https://benchmarkdotnet.org/articles/configs/configs.html) | ||
|
||
```csharp | ||
var config = ManualConfig | ||
.Create(DefaultConfig.Instance) | ||
.AddValidator(ExecutionValidator.FailOnError) | ||
.WithSummaryStyle(SummaryStyle.Default.WithRatioStyle(RatioStyle.Percentage)) | ||
.AddDiagnoser(MemoryDiagnoser.Default) | ||
.HideColumns("Median", "RatioSD", "Alloc Ratio") //"Error", "StdDev", | ||
.AddJob(Job.Default.WithRuntime(CoreRuntime.Core60)) | ||
.AddJob(Job.Default.WithRuntime(CoreRuntime.Core80)) | ||
; | ||
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, config); | ||
``` | ||
|
||
|
||
# Results | ||
1. [Exporters](https://benchmarkdotnet.org/articles/configs/exporters.html) | ||
2. [Charting](https://chartbenchmark.net/) | ||
3. [Plot for blogs](https://michalbrylka.github.io/posts/generic-math-matrix/#performance) | ||
|
||
|
||
# Utils | ||
1. [BenchmarkInput.cs](Helpers/BenchmarkInput.cs) |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
namespace Benchmarks.BestPractices; | ||
|
||
/* | ||
| Method | Runtime | Mean | Ratio | | ||
|----------------- |--------- |-----------:|---------:| | ||
| Yield | .NET 6.0 | 3,778.5 ns | baseline | | ||
| YieldLocalMethod | .NET 6.0 | 3,760.8 ns | -0% | | ||
| EnumerableRange | .NET 6.0 | 3,536.0 ns | -6% | | ||
| ArrayBench | .NET 6.0 | 850.7 ns | -77% | | ||
| | | | | | ||
| Yield | .NET 8.0 | 1,452.5 ns | baseline | | ||
| YieldLocalMethod | .NET 8.0 | 1,440.6 ns | -1% | | ||
| EnumerableRange | .NET 8.0 | 1,432.5 ns | -1% | | ||
| ArrayBench | .NET 8.0 | 753.2 ns | -48% | | ||
*/ | ||
public class GeneratorBench | ||
{ | ||
private const int SIZE = 1000; | ||
|
||
[Benchmark(Baseline = true)] | ||
public int Yield() | ||
{ | ||
int sum = 0; | ||
foreach (var i in Sequence()) | ||
sum += i; | ||
return sum; | ||
} | ||
|
||
static IEnumerable<int> Sequence() | ||
{ | ||
for (int i = 0; i < SIZE; i++) | ||
yield return i; | ||
} | ||
|
||
[Benchmark] | ||
public int YieldLocalMethod() | ||
{ | ||
int sum = 0; | ||
foreach (var i in SequenceLocal()) | ||
sum += i; | ||
return sum; | ||
|
||
static IEnumerable<int> SequenceLocal() | ||
{ | ||
for (int i = 0; i < SIZE; i++) | ||
yield return i; | ||
} | ||
} | ||
|
||
[Benchmark] | ||
public int EnumerableRange() | ||
{ | ||
int sum = 0; | ||
foreach (var i in Enumerable.Range(0, SIZE)) | ||
sum += i; | ||
return sum; | ||
} | ||
|
||
[Benchmark] | ||
public int ArrayBench() | ||
{ | ||
int sum = 0; | ||
foreach (var i in ArrayGen()) | ||
sum += i; | ||
return sum; | ||
} | ||
|
||
|
||
static int[] ArrayGen() | ||
{ | ||
var arr = new int[SIZE]; | ||
for (int i = 0; i < SIZE; i++) | ||
arr[i] = i; | ||
return arr; | ||
} | ||
} | ||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
/* | ||
| Method | Runtime | Mean | Ratio | Gen0 | Allocated | | ||
|----------------- |--------- |-----------:|---------:|-------:|----------:|- | ||
| Yield | .NET 6.0 | 3,778.5 ns | baseline | - | 32 B | | ||
| YieldLocalMethod | .NET 6.0 | 3,760.8 ns | -0% | 0.0038 | 32 B | | ||
| EnumerableRange | .NET 6.0 | 3,536.0 ns | -6% | 0.0038 | 40 B | | ||
| ArrayBench | .NET 6.0 | 850.7 ns | -77% | 0.6409 | 4024 B | | ||
| | | | | | | | ||
| Yield | .NET 8.0 | 1,452.5 ns | baseline | 0.0038 | 32 B | | ||
| YieldLocalMethod | .NET 8.0 | 1,440.6 ns | -1% | 0.0038 | 32 B | | ||
| EnumerableRange | .NET 8.0 | 1,432.5 ns | -1% | 0.0057 | 40 B | | ||
| ArrayBench | .NET 8.0 | 753.2 ns | -48% | 0.6409 | 4024 B | | ||
*/ |
Oops, something went wrong.