diff --git a/.gitignore b/.gitignore index 3babd98..f9d4413 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ obj packages .tools private.snk -.idea \ No newline at end of file +.idea +BenchmarkDotNet.Artifacts/ \ No newline at end of file diff --git a/Crc32.NET.Benchmarks/Crc32.NET.Benchmarks.csproj b/Crc32.NET.Benchmarks/Crc32.NET.Benchmarks.csproj new file mode 100644 index 0000000..920970e --- /dev/null +++ b/Crc32.NET.Benchmarks/Crc32.NET.Benchmarks.csproj @@ -0,0 +1,18 @@ + + + + Exe + net461;netcoreapp2.1;netcoreapp3.1 + + false + + + + + + + + + + + diff --git a/Crc32.NET.Benchmarks/Crc32.cs b/Crc32.NET.Benchmarks/Crc32.cs new file mode 100644 index 0000000..c177a49 --- /dev/null +++ b/Crc32.NET.Benchmarks/Crc32.cs @@ -0,0 +1,43 @@ +using System; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Jobs; +using Force.Crc32; + +namespace Crc32.NET.Benchmarks +{ + [SimpleJob(RuntimeMoniker.NetCoreApp31)] + public class Crc32 + { + private byte[] _input; + private byte[] _destination; + + [Params(65536)] + public int Size { get; set; } + + [GlobalSetup] + public void Setup() + { + _input = new byte[Size]; + var random = new Random(); + random.NextBytes(_input); + + _destination = new byte[4]; + } + + [Benchmark(Baseline = true)] + public byte[] Array() + { + var crc = new Crc32Algorithm(); + return crc.ComputeHash(_input); + } + +#if NETCOREAPP3_1 + [Benchmark] + public void Span() + { + var crc = new Crc32Algorithm(); + crc.TryComputeHash(_input.AsSpan(), _destination.AsSpan(), out _); + } +#endif + } +} diff --git a/Crc32.NET.Benchmarks/Program.cs b/Crc32.NET.Benchmarks/Program.cs new file mode 100644 index 0000000..452ff95 --- /dev/null +++ b/Crc32.NET.Benchmarks/Program.cs @@ -0,0 +1,10 @@ +using System; +using BenchmarkDotNet.Running; + +namespace Crc32.NET.Benchmarks +{ + class Program + { + static void Main(string[] args) => BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args, new StandardConfig()); + } +} diff --git a/Crc32.NET.Benchmarks/StandardConfig.cs b/Crc32.NET.Benchmarks/StandardConfig.cs new file mode 100644 index 0000000..b1e6538 --- /dev/null +++ b/Crc32.NET.Benchmarks/StandardConfig.cs @@ -0,0 +1,23 @@ +using BenchmarkDotNet.Columns; +using BenchmarkDotNet.Configs; +using BenchmarkDotNet.Exporters; +using BenchmarkDotNet.Loggers; + +namespace Crc32.NET.Benchmarks +{ + public class StandardConfig : ManualConfig + { + public StandardConfig() + { + AddColumnProvider(DefaultColumnProviders.Instance); + AddColumn(RankColumn.Arabic); + + AddExporter(DefaultExporters.CsvMeasurements); + AddExporter(DefaultExporters.Csv); + AddExporter(DefaultExporters.Markdown); + AddExporter(DefaultExporters.Html); + + AddLogger(ConsoleLogger.Default); + } + } +} diff --git a/Crc32.NET.Core.sln b/Crc32.NET.Core.sln index 51e72af..5bdbb30 100644 --- a/Crc32.NET.Core.sln +++ b/Crc32.NET.Core.sln @@ -1,17 +1,19 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.26114.2 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30611.23 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crc32.NET", "Crc32.NET\Crc32.NET.Core.csproj", "{E95FA3F3-4ED0-41FF-9A1F-DE80CE14A976}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crc32.NET.Core", "Crc32.NET\Crc32.NET.Core.csproj", "{E95FA3F3-4ED0-41FF-9A1F-DE80CE14A976}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crc32.NET.Tests", "Crc32.NET.Tests\Crc32.NET.Tests.Core.csproj", "{A602A9CA-793A-4096-A93C-799CA74519BF}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Crc32.NET.Tests.Core", "Crc32.NET.Tests\Crc32.NET.Tests.Core.csproj", "{A602A9CA-793A-4096-A93C-799CA74519BF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{56B92A80-3AE8-4FD0-B1F6-3847919216DA}" ProjectSection(SolutionItems) = preProject README.md = README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Crc32.NET.Benchmarks", "Crc32.NET.Benchmarks\Crc32.NET.Benchmarks.csproj", "{13C3DDAD-50F1-4804-95A1-D54766EA1247}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -26,8 +28,15 @@ Global {A602A9CA-793A-4096-A93C-799CA74519BF}.Debug|Any CPU.Build.0 = Debug|Any CPU {A602A9CA-793A-4096-A93C-799CA74519BF}.Release|Any CPU.ActiveCfg = Release|Any CPU {A602A9CA-793A-4096-A93C-799CA74519BF}.Release|Any CPU.Build.0 = Release|Any CPU + {13C3DDAD-50F1-4804-95A1-D54766EA1247}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {13C3DDAD-50F1-4804-95A1-D54766EA1247}.Debug|Any CPU.Build.0 = Debug|Any CPU + {13C3DDAD-50F1-4804-95A1-D54766EA1247}.Release|Any CPU.ActiveCfg = Release|Any CPU + {13C3DDAD-50F1-4804-95A1-D54766EA1247}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {A1461F74-929C-4C81-8E25-B44498AEEF6D} + EndGlobalSection EndGlobal diff --git a/Crc32.NET.Tests/Crc32.NET.Tests.Core.csproj b/Crc32.NET.Tests/Crc32.NET.Tests.Core.csproj index abd6655..699d45f 100644 --- a/Crc32.NET.Tests/Crc32.NET.Tests.Core.csproj +++ b/Crc32.NET.Tests/Crc32.NET.Tests.Core.csproj @@ -1,6 +1,6 @@  - netcoreapp1.0;netcoreapp2.0;net461 + netcoreapp1.0;netcoreapp2.0;netcoreapp3.1;net461 portable Crc32.NET.Tests Exe @@ -40,6 +40,9 @@ $(DefineConstants);NETCORE;NETCORE20 + + $(DefineConstants);NETCORE;NETCORE30 + $(DefineConstants);COREVERSION diff --git a/Crc32.NET.Tests/ImplementationTest.cs b/Crc32.NET.Tests/ImplementationTest.cs index 7bfe6da..2ff5fb9 100644 --- a/Crc32.NET.Tests/ImplementationTest.cs +++ b/Crc32.NET.Tests/ImplementationTest.cs @@ -1,4 +1,7 @@ using System; +#if NETCORE30 +using System.Buffers.Binary; +#endif using System.Linq; using System.Text; @@ -30,7 +33,7 @@ public void ResultConsistency(string text, int offset) Assert.That(crc2, Is.EqualTo(crc1)); } #endif - + [Test] public void ResultConsistency2() { @@ -52,7 +55,28 @@ public void ResultConsistencyAsHashAlgorithm() Console.WriteLine(crc2.ToString("X8")); Assert.That(crc1, Is.EqualTo(crc2)); } -#endif +#endif + +#if NETCORE30 + [Test] + public void ResultConsistencyAsHashAlgorithm_SpanVsArray() + { + var bytes = new byte[30000]; + new Random().NextBytes(bytes); + var e = new Crc32Algorithm(); + var c = new Crc32Algorithm(); + var crc1 = BitConverter.ToInt32(e.ComputeHash(bytes), 0); + + var dest = new byte[4]; + Assert.That(c.TryComputeHash(bytes, dest, out var bytesWritten), Is.True); + Assert.That(bytesWritten, Is.EqualTo(4)); + var crc2 = BinaryPrimitives.ReadInt32LittleEndian(dest); + + Console.WriteLine(crc1.ToString("X8")); + Console.WriteLine(crc2.ToString("X8")); + Assert.That(crc1, Is.EqualTo(crc2)); + } +#endif [Test] public void PartIsWhole() diff --git a/Crc32.NET/Crc32.NET.Core.csproj b/Crc32.NET/Crc32.NET.Core.csproj index cec1661..a2c3035 100644 --- a/Crc32.NET/Crc32.NET.Core.csproj +++ b/Crc32.NET/Crc32.NET.Core.csproj @@ -1,7 +1,7 @@  1.2.1 - netstandard1.3;netstandard2.0;net20 + netstandard1.3;netstandard2.0;netstandard2.1;net20 true Crc32.NET