Skip to content

Commit

Permalink
Update dependencies and make use of modern idioms (#16)
Browse files Browse the repository at this point in the history
  • Loading branch information
louis-z authored Aug 12, 2024
1 parent 8f48651 commit 46d2d4d
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 188 deletions.
10 changes: 3 additions & 7 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
version: 2
updates:
- package-ecosystem: nuget
directory: "/"
directory: '/'
schedule:
interval: monthly
time: "10:00"
interval: weekly
time: '10:00'
open-pull-requests-limit: 10
# ignore:
# - dependency-name: Microsoft.CodeAnalysis.FxCopAnalyzers
# versions:
# - 3.3.2
10 changes: 5 additions & 5 deletions IntroToSpans/IntroToSpans.csproj
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>11.0</LangVersion>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12.0</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0-preview1.23165.1">
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.435">
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
77 changes: 38 additions & 39 deletions IntroToSpans/Program.cs
Original file line number Diff line number Diff line change
@@ -1,52 +1,51 @@
using System;
using System.Runtime.InteropServices;

namespace IntroToSpans
namespace IntroToSpans;

/// <summary>
/// Getting familiar with Span<T>...
/// </summary>
/// <see href="https://github.com/dotnet/corefxlab/blob/master/docs/specs/span.md"/>
/// <see href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay"/>
internal class Program
{
/// <summary>
/// Getting familiar with Span<T>...
/// </summary>
/// <see href="https://github.com/dotnet/corefxlab/blob/master/docs/specs/span.md"/>
/// <see href="https://docs.microsoft.com/en-us/archive/msdn-magazine/2018/january/csharp-all-about-span-exploring-a-new-net-mainstay"/>
internal class Program
private static void Main()
{
private static void Main()
{
TestSpanWithAllMemoryTypes();
}
TestSpanWithAllMemoryTypes();
}

private static void TestSpanWithAllMemoryTypes()
{
// managed memory
var byteArray = new byte[100];
Span<byte> byteSpanOnManagedMemory = byteArray;

private static void TestSpanWithAllMemoryTypes()
// native memory
var nativeMemory = Marshal.AllocHGlobal(100);
Span<byte> byteSpanOnNativeMemory;
unsafe
{
// managed memory
var byteArray = new byte[100];
Span<byte> byteSpanOnManagedMemory = byteArray;

// native memory
var nativeMemory = Marshal.AllocHGlobal(100);
Span<byte> byteSpanOnNativeMemory;
unsafe
{
byteSpanOnNativeMemory = new Span<byte>(nativeMemory.ToPointer(), 100);
}

SafeSum(byteSpanOnNativeMemory);
Marshal.FreeHGlobal(nativeMemory);

// stack memory
Span<byte> byteSpanOnStackMemory = stackalloc byte[100];
SafeSum(byteSpanOnStackMemory);
byteSpanOnNativeMemory = new Span<byte>(nativeMemory.ToPointer(), 100);
}

// this method does not care what kind of memory it works on
private static ulong SafeSum(Span<byte> bytes)
{
ulong sum = 0;
for (var i = 0; i < bytes.Length; i++)
{
sum += bytes[i];
}
SafeSum(byteSpanOnNativeMemory);
Marshal.FreeHGlobal(nativeMemory);

// stack memory
Span<byte> byteSpanOnStackMemory = stackalloc byte[100];
SafeSum(byteSpanOnStackMemory);
}

return sum;
// this method does not care what kind of memory it works on
private static ulong SafeSum(Span<byte> bytes)
{
ulong sum = 0;
for (var i = 0; i < bytes.Length; i++)
{
sum += bytes[i];
}

return sum;
}
}
19 changes: 9 additions & 10 deletions SpanBenchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,20 @@
using BenchmarkDotNet.Running;
#endif

namespace TestingSpan
namespace TestingSpan;

internal static class Program
{
internal static class Program
private static void Main()
{
private static void Main()
{
#if DEBUG
var bm = new SpanBenchmarks();
var wordsFromSplit = bm.UseSplit();
var wordsFromSpan = bm.UseSpan();
var bm = new SpanBenchmarks();
var wordsFromSplit = bm.UseSplit();
var wordsFromSpan = bm.UseSpan();

Console.WriteLine($"Sequences are equal: {wordsFromSpan.SequenceEqual(wordsFromSplit)}");
Console.WriteLine($"Sequences are equal: {wordsFromSpan.SequenceEqual(wordsFromSplit)}");
#else
BenchmarkRunner.Run<SpanBenchmarks>();
BenchmarkRunner.Run<SpanBenchmarks>();
#endif
}
}
}
136 changes: 68 additions & 68 deletions SpanBenchmarks/SpanBenchmarks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,94 +6,94 @@
using BenchmarkDotNet.Attributes;
using static TestingSpan.StringExtensions;

namespace TestingSpan
namespace TestingSpan;

[MemoryDiagnoser]
public class SpanBenchmarks
{
[MemoryDiagnoser]
public class SpanBenchmarks
{
private const string MyText = @"
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Turpis egestas sed tempus urna. Vel pharetra vel turpis nunc eget lorem dolor. A diam sollicitudin tempor id
eu nisl. Nunc scelerisque viverra mauris in aliquam. Massa eget egestas purus viverra accumsan in. Fermentum et
sollicitud in ac orci phasellus egestas. Purus ut faucibus pulvinar elementum integer enim neque volutpat ac. Adipiscing
tristique risus nec feugiat in fermentum. Ut faucibus pulvinar elementum integer enim neque volutpat. Ipsum dolor sit
amet consectetur adipiscing elit ut aliquam. Donec et odio pellentesque diam volutpat commodo sed egestas. Congue nisi
vitae suscipit tellus mauris. Mi in nulla posuere sollicitudin aliquam ultrices sagittis orci a. Quam nulla porttitor
massa id neque aliquam vestibulum. Nisl suscipit adipiscing bibendum est ultricies integer. Imperdiet sed euismod nisi
porta lorem.
private const string MyText = """
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna
aliqua. Turpis egestas sed tempus urna. Vel pharetra vel turpis nunc eget lorem dolor. A diam sollicitudin tempor id
eu nisl. Nunc scelerisque viverra mauris in aliquam. Massa eget egestas purus viverra accumsan in. Fermentum et
sollicitud in ac orci phasellus egestas. Purus ut faucibus pulvinar elementum integer enim neque volutpat ac. Adipiscing
tristique risus nec feugiat in fermentum. Ut faucibus pulvinar elementum integer enim neque volutpat. Ipsum dolor sit
amet consectetur adipiscing elit ut aliquam. Donec et odio pellentesque diam volutpat commodo sed egestas. Congue nisi
vitae suscipit tellus mauris. Mi in nulla posuere sollicitudin aliquam ultrices sagittis orci a. Quam nulla porttitor
massa id neque aliquam vestibulum. Nisl suscipit adipiscing bibendum est ultricies integer. Imperdiet sed euismod nisi
porta lorem.

Viverra nibh cras pulvinar mattis. Lorem mollis aliquam ut porttitor. Tellus in hac habitasse platea dictumst vestibulum
rhoncus est pellentesque. Sed cras ornare arcu dui vivamus arcu felis. Blandit volutpat maecenas volutpat blandit
aliquam etiam erat velit. Eu augue ut lectus arcu bibendum at varius vel pharetra. Senectus et netus et malesuada fames
ac turpis. At volutpat diam ut venenatis. Adipiscing at in tellus integer feugiat scelerisque. Diam quis enim lobortis
scelerisque fermentum dui faucibus in. Nibh tellus molestie nunc non. Phasellus faucibus scelerisque eleifend donec.
Porta nibh venenatis cras sed. Consequat id porta nibh venenatis. Leo vel fringilla est ullamcorper eget.
Viverra nibh cras pulvinar mattis. Lorem mollis aliquam ut porttitor. Tellus in hac habitasse platea dictumst vestibulum
rhoncus est pellentesque. Sed cras ornare arcu dui vivamus arcu felis. Blandit volutpat maecenas volutpat blandit
aliquam etiam erat velit. Eu augue ut lectus arcu bibendum at varius vel pharetra. Senectus et netus et malesuada fames
ac turpis. At volutpat diam ut venenatis. Adipiscing at in tellus integer feugiat scelerisque. Diam quis enim lobortis
scelerisque fermentum dui faucibus in. Nibh tellus molestie nunc non. Phasellus faucibus scelerisque eleifend donec.
Porta nibh venenatis cras sed. Consequat id porta nibh venenatis. Leo vel fringilla est ullamcorper eget.

Cursus mattis molestie a iaculis at erat pellentesque adipiscing. Non enim praesent elementum facilisis leo vel
fringilla est ullamcorper. Augue interdum velit euismod in pellentesque massa placerat. Habitasse platea dictumst
quisque sagittis purus sit amet volutpat consequat. Volutpat est velit egestas dui id. Neque laoreet suspendisse
interdum consectetur. Nunc aliquet bibendum enim facilisis. Curabitur gravida arcu ac tortor dignissim convallis aenean
et tortor. Sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. Amet nisl purus in mollis nunc sed id semper.
Enim blandit volutpat maecenas volutpat blandit aliquam. Mauris pharetra et ultrices neque ornare aenean. Et leo duis ut
diam quam. In nisl nisi scelerisque eu ultrices. Felis eget nunc lobortis mattis aliquam. Faucibus a pellentesque sit
amet porttitor eget dolor morbi. Sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque eu. Odio ut
enim blandit volutpat maecenas volutpat blandit. Diam sollicitudin tempor id eu nisl nunc mi.
Cursus mattis molestie a iaculis at erat pellentesque adipiscing. Non enim praesent elementum facilisis leo vel
fringilla est ullamcorper. Augue interdum velit euismod in pellentesque massa placerat. Habitasse platea dictumst
quisque sagittis purus sit amet volutpat consequat. Volutpat est velit egestas dui id. Neque laoreet suspendisse
interdum consectetur. Nunc aliquet bibendum enim facilisis. Curabitur gravida arcu ac tortor dignissim convallis aenean
et tortor. Sagittis nisl rhoncus mattis rhoncus urna neque viverra justo. Amet nisl purus in mollis nunc sed id semper.
Enim blandit volutpat maecenas volutpat blandit aliquam. Mauris pharetra et ultrices neque ornare aenean. Et leo duis ut
diam quam. In nisl nisi scelerisque eu ultrices. Felis eget nunc lobortis mattis aliquam. Faucibus a pellentesque sit
amet porttitor eget dolor morbi. Sollicitudin ac orci phasellus egestas tellus rutrum tellus pellentesque eu. Odio ut
enim blandit volutpat maecenas volutpat blandit. Diam sollicitudin tempor id eu nisl nunc mi.

Praesent tristique magna sit amet purus. Cursus mattis molestie a iaculis. Lectus arcu bibendum at varius vel pharetra
vel turpis. Ultrices neque ornare aenean euismod elementum nisi quis. Morbi tristique senectus et netus et malesuada
fames. Magna eget est lorem ipsum dolor sit amet consectetur adipiscing. Hac habitasse platea dictumst quisque sagittis.
Nunc id cursus metus aliquam eleifend mi in nulla posuere. Ultrices dui sapien eget mi proin sed libero enim. Id neque
aliquam vestibulum morbi. Nunc id cursus metus aliquam eleifend mi. Dui ut ornare lectus sit. Suscipit tellus mauris a
diam maecenas sed enim ut.
Praesent tristique magna sit amet purus. Cursus mattis molestie a iaculis. Lectus arcu bibendum at varius vel pharetra
vel turpis. Ultrices neque ornare aenean euismod elementum nisi quis. Morbi tristique senectus et netus et malesuada
fames. Magna eget est lorem ipsum dolor sit amet consectetur adipiscing. Hac habitasse platea dictumst quisque sagittis.
Nunc id cursus metus aliquam eleifend mi in nulla posuere. Ultrices dui sapien eget mi proin sed libero enim. Id neque
aliquam vestibulum morbi. Nunc id cursus metus aliquam eleifend mi. Dui ut ornare lectus sit. Suscipit tellus mauris a
diam maecenas sed enim ut.

Nascetur ridiculus mus mauris vitae ultricies leo integer malesuada nunc. Quisque non tellus orci ac. Risus commodo
viverra maecenas accumsan lacus. Diam ut venenatis tellus in metus vulputate eu scelerisque. Elementum eu facilisis sed
odio. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Arcu felis bibendum ut tristique et
egestas quis. In ornare quam viverra orci sagittis eu volutpat odio facilisis. Nec tincidunt praesent semper feugiat
nibh sed pulvinar proin. Condimentum id venenatis a condimentum vitae sapien pellentesque habitant. Ac turpis egestas
maecenas pharetra convallis posuere morbi leo urna. Proin sagittis nisl rhoncus mattis rhoncus urna neque. Nisi lacus
sed viverra tellus. Euismod quis viverra nibh cras pulvinar mattis nunc sed blandit. Scelerisque viverra mauris in
aliquam sem. Habitant morbi tristique senectus et netus et malesuada. Consectetur adipiscing elit duis tristique
sollicitudin nibh sit amet commodo.";
Nascetur ridiculus mus mauris vitae ultricies leo integer malesuada nunc. Quisque non tellus orci ac. Risus commodo
viverra maecenas accumsan lacus. Diam ut venenatis tellus in metus vulputate eu scelerisque. Elementum eu facilisis sed
odio. Vitae sapien pellentesque habitant morbi tristique senectus et netus et. Arcu felis bibendum ut tristique et
egestas quis. In ornare quam viverra orci sagittis eu volutpat odio facilisis. Nec tincidunt praesent semper feugiat
nibh sed pulvinar proin. Condimentum id venenatis a condimentum vitae sapien pellentesque habitant. Ac turpis egestas
maecenas pharetra convallis posuere morbi leo urna. Proin sagittis nisl rhoncus mattis rhoncus urna neque. Nisi lacus
sed viverra tellus. Euismod quis viverra nibh cras pulvinar mattis nunc sed blandit. Scelerisque viverra mauris in
aliquam sem. Habitant morbi tristique senectus et netus et malesuada. Consectetur adipiscing elit duis tristique
sollicitudin nibh sit amet commodo.
""";

[Benchmark(Baseline = true)]
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Benchmarks MUST be instance methods")]
public string[] UseSplit()
{
[Benchmark(Baseline = true)]
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Benchmarks MUST be instance methods")]
public string[] UseSplit()
{
#if DEBUG
var words = new List<string>();
var words = new List<string>();
#endif
foreach (var word in MyText.Split(WordSeparators, StringSplitOptions.RemoveEmptyEntries))
{
foreach (var word in MyText.Split(WordSeparators, StringSplitOptions.RemoveEmptyEntries))
{
#if DEBUG
words.Add(word);
words.Add(word);
#endif
}
}
#if DEBUG
return words.ToArray();
return words.ToArray();
#else
return Array.Empty<string>();
return [];
#endif
}
}

[Benchmark]
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Benchmarks MUST be instance methods")]
public string[] UseSpan()
{
[Benchmark]
[SuppressMessage("Performance", "CA1822:Mark members as static", Justification = "Benchmarks MUST be instance methods")]
public string[] UseSpan()
{
#if DEBUG
var words = new List<string>();
var words = new List<string>();
#endif
foreach (var word in MyText.SplitIntoWords())
{
foreach (var word in MyText.SplitIntoWords())
{
#if DEBUG
words.Add(word.ToString());
words.Add(word.ToString());
#endif
}
}
#if DEBUG
return words.ToArray();
return words.ToArray();
#else
return Array.Empty<string>();
return [];
#endif
}
}
}
10 changes: 5 additions & 5 deletions SpanBenchmarks/SpanBenchmarks.csproj
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<LangVersion>11.0</LangVersion>
<TargetFramework>net8.0</TargetFramework>
<LangVersion>12.0</LangVersion>
<Deterministic>true</Deterministic>
<Features>strict</Features>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="BenchmarkDotNet" Version="0.13.5" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0-preview1.23165.1">
<PackageReference Include="BenchmarkDotNet" Version="0.14.0" />
<PackageReference Include="Microsoft.CodeAnalysis.NetAnalyzers" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
Expand Down
15 changes: 7 additions & 8 deletions SpanBenchmarks/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
using System;

namespace TestingSpan
namespace TestingSpan;

public static class StringExtensions
{
public static class StringExtensions
{
public static readonly char[] WordSeparators = new[] { ' ', '\r', '\n', '\t' };
public static readonly char[] WordSeparators = [' ', '\r', '\n', '\t'];

public static WordEnumerator SplitIntoWords(this string str)
{
return new WordEnumerator(str.AsSpan()); // WordEnumerator is a struct -> no heap allocation here
}
public static WordEnumerator SplitIntoWords(this string str)
{
return new WordEnumerator(str.AsSpan()); // WordEnumerator is a struct -> no heap allocation here
}
}
Loading

0 comments on commit 46d2d4d

Please sign in to comment.