diff --git a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/Benchmarks.csproj b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/Benchmarks.csproj new file mode 100644 index 000000000..f1f8bf88d --- /dev/null +++ b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/Benchmarks.csproj @@ -0,0 +1,14 @@ + + + + Exe + net10.0 + enable + enable + + + + + + + diff --git a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/Program.cs b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/Program.cs new file mode 100644 index 000000000..60ea5cc54 --- /dev/null +++ b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/Program.cs @@ -0,0 +1,4 @@ +using BenchmarkDotNet.Running; +using SpanMemoryBench; + +BenchmarkRunner.Run(); diff --git a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/SpanVsMemoryReadBenchmark.cs b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/SpanVsMemoryReadBenchmark.cs new file mode 100644 index 000000000..c6054fec3 --- /dev/null +++ b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/Benchmarks/SpanVsMemoryReadBenchmark.cs @@ -0,0 +1,64 @@ +using BenchmarkDotNet.Attributes; + +namespace SpanMemoryBench; + +// The published benchmark slices a six element array once per operation, which lands under a +// nanosecond and is swamped by timer noise. This one reads a whole buffer, which is the work a +// caller actually does, and it separates the two ways of reading through Memory: asking for the +// Span on every element, and taking the Span once and looping over that. +[MemoryDiagnoser] +public class SpanVsMemoryReadBenchmark +{ + private readonly int[] _data = CreateData(); + + private static int[] CreateData() + { + var data = new int[4096]; + for (var i = 0; i < data.Length; i++) + { + data[i] = i; + } + + return data; + } + + [Benchmark(Description = "Sum through Span")] + public int SumThroughSpan() + { + var span = _data.AsSpan(); + var sum = 0; + for (var i = 0; i < span.Length; i++) + { + sum += span[i]; + } + + return sum; + } + + [Benchmark(Description = "Sum through Memory.Span per element")] + public int SumThroughMemory() + { + var memory = _data.AsMemory(); + var sum = 0; + for (var i = 0; i < memory.Length; i++) + { + sum += memory.Span[i]; + } + + return sum; + } + + [Benchmark(Description = "Sum through Memory, Span taken once")] + public int SumThroughMemorySpanTakenOnce() + { + var memory = _data.AsMemory(); + var span = memory.Span; + var sum = 0; + for (var i = 0; i < span.Length; i++) + { + sum += span[i]; + } + + return sum; + } +} diff --git a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.sln b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.sln index 95440992a..ec4d51985 100644 --- a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.sln +++ b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.sln @@ -5,16 +5,42 @@ VisualStudioVersion = 17.8.34525.116 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DifferencesBetweenSpanAndMemoryInCSharp", "DifferencesBetweenSpanAndMemoryInCSharp\DifferencesBetweenSpanAndMemoryInCSharp.csproj", "{B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Benchmarks", "Benchmarks\Benchmarks.csproj", "{E940AB59-73DD-4930-AA0F-3B8901377AE3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU + Debug|x64 = Debug|x64 + Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU + Release|x64 = Release|x64 + Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Debug|x64.ActiveCfg = Debug|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Debug|x64.Build.0 = Debug|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Debug|x86.ActiveCfg = Debug|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Debug|x86.Build.0 = Debug|Any CPU {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Release|Any CPU.ActiveCfg = Release|Any CPU {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Release|Any CPU.Build.0 = Release|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Release|x64.ActiveCfg = Release|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Release|x64.Build.0 = Release|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Release|x86.ActiveCfg = Release|Any CPU + {B9131A15-948F-4A88-B38C-ED4D4D1C4DB1}.Release|x86.Build.0 = Release|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Debug|x64.ActiveCfg = Debug|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Debug|x64.Build.0 = Debug|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Debug|x86.ActiveCfg = Debug|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Debug|x86.Build.0 = Debug|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Release|Any CPU.Build.0 = Release|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Release|x64.ActiveCfg = Release|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Release|x64.Build.0 = Release|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Release|x86.ActiveCfg = Release|Any CPU + {E940AB59-73DD-4930-AA0F-3B8901377AE3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.csproj b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.csproj index af4ee328c..12933579a 100644 --- a/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.csproj +++ b/dotnet-performance/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp/DifferencesBetweenSpanAndMemoryInCSharp.csproj @@ -8,7 +8,7 @@ - +