Skip to content

Instantly share code, notes, and snippets.

@jl0pd
Created April 6, 2021 05:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jl0pd/7501c6d1143e6c0c5886a5949de00aea to your computer and use it in GitHub Desktop.
Save jl0pd/7501c6d1143e6c0c5886a5949de00aea to your computer and use it in GitHub Desktop.
C# Unsafe and semi-safe sum
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;
namespace SumTest
{
class Program
{
static void Main(string[] args)
{
BenchmarkRunner.Run<TestSafeAndUnsafeSum>();
}
}
[DisassemblyDiagnoser]
public class TestSafeAndUnsafeSum
{
public IEnumerable<object[]> Data()
{
yield return new object[] { Enumerable.Range(0, 100_000).ToArray(), 100_000 };
yield return new object[] { Enumerable.Range(0, 1_000_000).ToArray(), 1_000_000 };
yield return new object[] { Enumerable.Range(0, 10_000_000).ToArray(), 10_000_000 };
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
[ArgumentsSource(nameof(Data))]
public int SumDirect(int[] ints, int length)
{
int sum = 0;
for (int i = 0; i < ints.Length; i++)
{
sum += ints[i];
}
return sum;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static T FastAccessValue<T>(T[] ar, int index)
{
ref T tableRef = ref MemoryMarshal.GetArrayDataReference(ar);
return Unsafe.Add(ref tableRef, (nint)index);
}
[Benchmark]
[MethodImpl(MethodImplOptions.NoInlining)]
[ArgumentsSource(nameof(Data))]
public int SumUnsafe(int[] ints, int length)
{
int sum = 0;
for (int i = 0; i < length; i++)
{
sum += FastAccessValue(ints, i);
}
return sum;
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.12.1" />
</ItemGroup>
</Project>
@jl0pd
Copy link
Author

jl0pd commented Apr 6, 2021

Run result

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19042
Intel Core i7-9750H CPU 2.60GHz, 1 CPU, 12 logical and 6 physical cores
.NET Core SDK=5.0.201
  [Host]     : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT
  DefaultJob : .NET Core 5.0.4 (CoreCLR 5.0.421.11614, CoreFX 5.0.421.11614), X64 RyuJIT

Method ints length Mean Error StdDev Code Size
SumDirect Int32[100000] 100000 80.13 μs 0.748 μs 0.700 μs 29 B
SumUnsafe Int32[100000] 100000 81.99 μs 0.535 μs 0.446 μs 33 B
SumDirect Int32[1000000] 1000000 854.73 μs 5.216 μs 4.624 μs 29 B
SumUnsafe Int32[1000000] 1000000 795.10 μs 2.680 μs 2.238 μs 33 B
SumDirect Int32[10000000] 10000000 10,104.72 μs 27.199 μs 22.712 μs 29 B
SumUnsafe Int32[10000000] 10000000 9,126.06 μs 30.329 μs 26.886 μs 33 B

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment