From ef34172fe9f638b5927eb1b7b00d3d8c223f0986 Mon Sep 17 00:00:00 2001 From: Chad Tolkien Date: Thu, 30 Apr 2020 16:22:49 +1000 Subject: [PATCH 1/3] WIP --- Slugify.sln | 15 ++++ src/Slugify.Core/SlugHelper.cs | 75 +++++++++++++++++-- src/Slugify.Core/Slugify.Core.csproj | 1 + ...chmarks.SlugifyBenchmarks-report-github.md | 17 +++++ ...re.Benchmarks.SlugifyBenchmarks-report.csv | 5 ++ ...e.Benchmarks.SlugifyBenchmarks-report.html | 33 ++++++++ tests/Slugify.Core.Benchmarks/Program.cs | 55 ++++++++++++++ .../Slugify.Core.Benchmarks.csproj | 17 +++++ tests/Slugify.Core.Tests/SlugHelperTests.cs | 6 +- 9 files changed, 215 insertions(+), 9 deletions(-) create mode 100644 tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md create mode 100644 tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv create mode 100644 tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html create mode 100644 tests/Slugify.Core.Benchmarks/Program.cs create mode 100644 tests/Slugify.Core.Benchmarks/Slugify.Core.Benchmarks.csproj diff --git a/Slugify.sln b/Slugify.sln index 50f51c7..55b7f7f 100644 --- a/Slugify.sln +++ b/Slugify.sln @@ -10,6 +10,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Slugify.Core", "src\Slugify EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Slugify.Core.Tests", "tests\Slugify.Core.Tests\Slugify.Core.Tests.csproj", "{A3717955-9FC4-41EB-B389-1A610D64B3B6}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Slugify.Core.Benchmarks", "tests\Slugify.Core.Benchmarks\Slugify.Core.Benchmarks.csproj", "{A859F823-7992-4820-905C-640F3440BAF2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -44,6 +46,18 @@ Global {A3717955-9FC4-41EB-B389-1A610D64B3B6}.Release|x64.Build.0 = Release|Any CPU {A3717955-9FC4-41EB-B389-1A610D64B3B6}.Release|x86.ActiveCfg = Release|Any CPU {A3717955-9FC4-41EB-B389-1A610D64B3B6}.Release|x86.Build.0 = Release|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Debug|x64.ActiveCfg = Debug|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Debug|x64.Build.0 = Debug|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Debug|x86.ActiveCfg = Debug|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Debug|x86.Build.0 = Debug|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Release|Any CPU.Build.0 = Release|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Release|x64.ActiveCfg = Release|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Release|x64.Build.0 = Release|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Release|x86.ActiveCfg = Release|Any CPU + {A859F823-7992-4820-905C-640F3440BAF2}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -51,6 +65,7 @@ Global GlobalSection(NestedProjects) = preSolution {CC5D3071-57A3-442C-8ACC-E543DA0A8E20} = {321AAEAA-F675-4B15-80B5-3FF2E6A15602} {A3717955-9FC4-41EB-B389-1A610D64B3B6} = {28DEE6D8-053D-4364-9DD5-F3744E58CF54} + {A859F823-7992-4820-905C-640F3440BAF2} = {28DEE6D8-053D-4364-9DD5-F3744E58CF54} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {189B8864-9AE7-4F2D-BFAC-5368F94F26E2} diff --git a/src/Slugify.Core/SlugHelper.cs b/src/Slugify.Core/SlugHelper.cs index 3836263..6a900c7 100644 --- a/src/Slugify.Core/SlugHelper.cs +++ b/src/Slugify.Core/SlugHelper.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Text; using System.Text.RegularExpressions; +using System.Xml; namespace Slugify { @@ -45,6 +46,72 @@ public string GenerateSlug(string inputString) return inputString; } + public string GenerateSlug2(string inputString) + { + if (_config.TrimWhitespace) + { + inputString = inputString.Trim(); + } + + if (_config.ForceLowerCase) + { + inputString = inputString.ToLower(); + } + + inputString = CleanWhiteSpace(inputString, _config.CollapseWhiteSpace); + inputString = ApplyReplacements(inputString, _config.StringReplacements); + inputString = RemoveDiacritics(inputString); + inputString = DeleteCharacters(inputString, _config.DeniedCharactersRegex); + + if (_config.CollapseDashes) + { + inputString = Regex.Replace(inputString, "--+", "-"); + } + + return inputString; + + string CleanWhiteSpace(string str, bool collapse) + { + return Regex.Replace(str, collapse ? @"\s+" : @"\s", " "); + } + + string RemoveDiacritics(string str) + { + var stFormD = str.Normalize(NormalizationForm.FormD); + var sb = new StringBuilder(stFormD.Length); + + + for (var ich = 0; ich < stFormD.Length; ich++) + { + var uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]); + if (uc != UnicodeCategory.NonSpacingMark) + { + sb.Append(stFormD[ich]); + } + } + + return sb.ToString().Normalize(NormalizationForm.FormC); + } + + + string ApplyReplacements(string str, Dictionary replacements) + { + foreach (var replacement in replacements) + { + str = str.Replace(replacement.Key, replacement.Value); + } + + return str; + } + + string DeleteCharacters(string str, string regex) + { + return Regex.Replace(str, regex, ""); + } + + } + + protected string CleanWhiteSpace(string str, bool collapse) { return Regex.Replace(str, collapse ? @"\s+" : @"\s", " "); @@ -90,15 +157,11 @@ protected string DeleteCharacters(string str, string regex) /// public class Config { - public Config() - { - StringReplacements = new Dictionary + public Dictionary StringReplacements { get; set; } = new Dictionary { { " ", "-" } }; - } - - public Dictionary StringReplacements { get; set; } + public bool ForceLowerCase { get; set; } = true; public bool CollapseWhiteSpace { get; set; } = true; public string DeniedCharactersRegex { get; set; } = @"[^a-zA-Z0-9\-\._]"; diff --git a/src/Slugify.Core/Slugify.Core.csproj b/src/Slugify.Core/Slugify.Core.csproj index 451aec5..f83b66f 100644 --- a/src/Slugify.Core/Slugify.Core.csproj +++ b/src/Slugify.Core/Slugify.Core.csproj @@ -34,6 +34,7 @@ With default settings, you will get an hyphenized, lowercase, alphanumeric versi all runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md new file mode 100644 index 0000000..d325c40 --- /dev/null +++ b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md @@ -0,0 +1,17 @@ +``` ini + +BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.778 (1909/November2018Update/19H2) +Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores +.NET Core SDK=3.1.201 + [Host] : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT + DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT + + +``` +| Method | N | word | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | +|--------- |-- |--------------------- |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| +| **Baseline** | **1** | **Hello** | **660.0 ns** | **2.01 ns** | **1.78 ns** | **1.00** | **0.00** | **0.0734** | **-** | **-** | **616 B** | +| Improved | 1 | Hello | 643.8 ns | 12.74 ns | 11.92 ns | 0.98 | 0.02 | 0.0553 | - | - | 464 B | +| | | | | | | | | | | | | +| **Baseline** | **1** | **lorem(...)oot!! [40]** | **4,174.1 ns** | **11.46 ns** | **10.72 ns** | **1.00** | **0.00** | **0.4501** | **-** | **-** | **3824 B** | +| Improved | 1 | lorem(...)oot!! [40] | 3,924.9 ns | 7.03 ns | 5.87 ns | 0.94 | 0.00 | 0.3967 | - | - | 3360 B | diff --git a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv new file mode 100644 index 0000000..7e5a40e --- /dev/null +++ b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv @@ -0,0 +1,5 @@ +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,N,word,Mean,Error,StdDev,Ratio,RatioSD,Gen 0,Gen 1,Gen 2,Allocated +Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,Hello,660.0 ns,2.01 ns,1.78 ns,1.00,0.00,0.0734,0.0000,0.0000,616 B +Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,Hello,643.8 ns,12.74 ns,11.92 ns,0.98,0.02,0.0553,0.0000,0.0000,464 B +Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,lorem(...)oot!! [40],"4,174.1 ns",11.46 ns,10.72 ns,1.00,0.00,0.4501,0.0000,0.0000,3824 B +Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,lorem(...)oot!! [40],"3,924.9 ns",7.03 ns,5.87 ns,0.94,0.00,0.3967,0.0000,0.0000,3360 B diff --git a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html new file mode 100644 index 0000000..8a6fede --- /dev/null +++ b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html @@ -0,0 +1,33 @@ + + + + +Slugify.Core.Benchmarks.SlugifyBenchmarks-20200430-160656 + + + + +

+BenchmarkDotNet=v0.12.1, OS=Windows 10.0.18363.778 (1909/November2018Update/19H2)
+Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical cores
+.NET Core SDK=3.1.201
+  [Host]     : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
+  DefaultJob : .NET Core 3.1.3 (CoreCLR 4.700.20.11803, CoreFX 4.700.20.12001), X64 RyuJIT
+
+
+ + + + + + + + +
MethodN wordMeanErrorStdDevRatioRatioSDGen 0Gen 1Gen 2Allocated
Baseline1Hello660.0 ns2.01 ns1.78 ns1.000.000.0734--616 B
Improved1Hello643.8 ns12.74 ns11.92 ns0.980.020.0553--464 B
Baseline1lorem(...)oot!! [40]4,174.1 ns11.46 ns10.72 ns1.000.000.4501--3824 B
Improved1lorem(...)oot!! [40]3,924.9 ns7.03 ns5.87 ns0.940.000.3967--3360 B
+ + diff --git a/tests/Slugify.Core.Benchmarks/Program.cs b/tests/Slugify.Core.Benchmarks/Program.cs new file mode 100644 index 0000000..40a3f8f --- /dev/null +++ b/tests/Slugify.Core.Benchmarks/Program.cs @@ -0,0 +1,55 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Running; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace Slugify.Core.Benchmarks +{ + internal class Program + { + private static void Main(string[] args) + { + var summary = BenchmarkRunner.Run(); + } + } + + [MemoryDiagnoser] + public class SlugifyBenchmarks + { + private SlugHelper _slugHelper; + + [GlobalSetup] + public void GlobalSetup() + { + _slugHelper = new SlugHelper(); + } + + [Params(1)] + public int N; + + [Params("Hello", "lorem & ipsome Some Other thing!_ woot!!")] + public string word; + + [Benchmark(Baseline = true)] + public void Baseline() + { + for (int i = 0; i < N; i++) + { + _slugHelper.GenerateSlug(word); + } + } + + [Benchmark] + public void Improved() + { + for (int i = 0; i < N; i++) + { + _slugHelper.GenerateSlug2(word); + } + } + + + } +} diff --git a/tests/Slugify.Core.Benchmarks/Slugify.Core.Benchmarks.csproj b/tests/Slugify.Core.Benchmarks/Slugify.Core.Benchmarks.csproj new file mode 100644 index 0000000..500935c --- /dev/null +++ b/tests/Slugify.Core.Benchmarks/Slugify.Core.Benchmarks.csproj @@ -0,0 +1,17 @@ + + + + Exe + netcoreapp3.1 + + + + + + + + + + + + diff --git a/tests/Slugify.Core.Tests/SlugHelperTests.cs b/tests/Slugify.Core.Tests/SlugHelperTests.cs index 6e3d366..1a61075 100644 --- a/tests/Slugify.Core.Tests/SlugHelperTests.cs +++ b/tests/Slugify.Core.Tests/SlugHelperTests.cs @@ -12,7 +12,7 @@ public void TestEmptyConfig() var config = new SlugHelper.Config(); Assert.True(config.ForceLowerCase); Assert.True(config.CollapseWhiteSpace); - Assert.Equal(1, config.StringReplacements.Count); + Assert.Single(config.StringReplacements); Assert.NotNull(new Regex(config.DeniedCharactersRegex)); } @@ -21,7 +21,7 @@ public void TestDefaultConfig() { var config = new SlugHelper.Config(); - Assert.Equal(1, config.StringReplacements.Count); + Assert.Single(config.StringReplacements); Assert.Equal("-", config.StringReplacements[" "]); } @@ -46,7 +46,7 @@ public void TestLoweCaseEnforcement() var helper = new SlugHelper(); - Assert.Equal(expected, helper.GenerateSlug(original)); + Assert.Equal(expected, helper.GenerateSlug2(original)); } [Fact] From 02e077bb3ecaf8b645ec1c367cb5c53d5a61f266 Mon Sep 17 00:00:00 2001 From: Chad Tolkien Date: Thu, 30 Apr 2020 17:59:01 +1000 Subject: [PATCH 2/3] WIP! --- src/Slugify.Core/SlugHelper.cs | 66 - src/Slugify.Core/SlugHelperImproved.cs | 100 + src/Slugify.Core/Slugify.Core.csproj | 1 + ...chmarks.SlugifyBenchmarks-report-github.md | 11 +- ...re.Benchmarks.SlugifyBenchmarks-report.csv | 8 +- ...e.Benchmarks.SlugifyBenchmarks-report.html | 10 +- tests/Slugify.Core.Benchmarks/Program.cs | 25 +- .../Slugify.Core.Benchmarks.csproj | 6 + tests/Slugify.Core.Benchmarks/gistfile.txt | 9418 +++++++++++++++++ tests/Slugify.Core.Tests/SlugHelperTests.cs | 38 +- 10 files changed, 9568 insertions(+), 115 deletions(-) create mode 100644 src/Slugify.Core/SlugHelperImproved.cs create mode 100644 tests/Slugify.Core.Benchmarks/gistfile.txt diff --git a/src/Slugify.Core/SlugHelper.cs b/src/Slugify.Core/SlugHelper.cs index 6a900c7..33accc2 100644 --- a/src/Slugify.Core/SlugHelper.cs +++ b/src/Slugify.Core/SlugHelper.cs @@ -46,72 +46,6 @@ public string GenerateSlug(string inputString) return inputString; } - public string GenerateSlug2(string inputString) - { - if (_config.TrimWhitespace) - { - inputString = inputString.Trim(); - } - - if (_config.ForceLowerCase) - { - inputString = inputString.ToLower(); - } - - inputString = CleanWhiteSpace(inputString, _config.CollapseWhiteSpace); - inputString = ApplyReplacements(inputString, _config.StringReplacements); - inputString = RemoveDiacritics(inputString); - inputString = DeleteCharacters(inputString, _config.DeniedCharactersRegex); - - if (_config.CollapseDashes) - { - inputString = Regex.Replace(inputString, "--+", "-"); - } - - return inputString; - - string CleanWhiteSpace(string str, bool collapse) - { - return Regex.Replace(str, collapse ? @"\s+" : @"\s", " "); - } - - string RemoveDiacritics(string str) - { - var stFormD = str.Normalize(NormalizationForm.FormD); - var sb = new StringBuilder(stFormD.Length); - - - for (var ich = 0; ich < stFormD.Length; ich++) - { - var uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]); - if (uc != UnicodeCategory.NonSpacingMark) - { - sb.Append(stFormD[ich]); - } - } - - return sb.ToString().Normalize(NormalizationForm.FormC); - } - - - string ApplyReplacements(string str, Dictionary replacements) - { - foreach (var replacement in replacements) - { - str = str.Replace(replacement.Key, replacement.Value); - } - - return str; - } - - string DeleteCharacters(string str, string regex) - { - return Regex.Replace(str, regex, ""); - } - - } - - protected string CleanWhiteSpace(string str, bool collapse) { return Regex.Replace(str, collapse ? @"\s+" : @"\s", " "); diff --git a/src/Slugify.Core/SlugHelperImproved.cs b/src/Slugify.Core/SlugHelperImproved.cs new file mode 100644 index 0000000..5960694 --- /dev/null +++ b/src/Slugify.Core/SlugHelperImproved.cs @@ -0,0 +1,100 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Text; +using System.Text.RegularExpressions; +using System.Xml; + +namespace Slugify +{ + public class SlugHelperImproved : ISlugHelper + { + protected SlugHelper.Config _config { get; set; } + + private readonly Regex _deniedCharactersRegex; + private readonly Regex _cleanWhiteSpaceRegex; + private readonly Regex _collapseDashesRegex; + + public SlugHelperImproved() : this(new SlugHelper.Config()) { } + + public SlugHelperImproved(SlugHelper.Config config) + { + _config = config ?? throw new ArgumentNullException(nameof(config), "can't be null use default config or empty constructor."); + + _deniedCharactersRegex = new Regex(_config.DeniedCharactersRegex, RegexOptions.Compiled); + _cleanWhiteSpaceRegex = new Regex(_config.CollapseWhiteSpace ? @"\s+" : @"\s", RegexOptions.Compiled); + _collapseDashesRegex = new Regex("--+", RegexOptions.Compiled); + } + + /// + /// Implements + /// + public string GenerateSlug(string inputString) + { + if (_config.TrimWhitespace) + { + inputString = inputString.Trim(); + } + + if (_config.ForceLowerCase) + { + inputString = inputString.ToLower(); + } + + inputString = CleanWhiteSpace(inputString); + inputString = ApplyReplacements(inputString); + inputString = RemoveDiacritics(inputString); + inputString = DeleteCharacters(inputString); + + if (_config.CollapseDashes) + { + inputString = _collapseDashesRegex.Replace(inputString, "-"); + } + + return inputString; + } + + + protected string CleanWhiteSpace(string str) + { + return _cleanWhiteSpaceRegex.Replace(str, " "); + } + + // Thanks http://stackoverflow.com/a/249126! + protected string RemoveDiacritics(string str) + { + var stFormD = str.Normalize(NormalizationForm.FormD); + + //perf: initialise this with the length of the chars + var sb = new StringBuilder(stFormD.Length); + + for (var ich = 0; ich < stFormD.Length; ich++) + { + var uc = CharUnicodeInfo.GetUnicodeCategory(stFormD[ich]); + if (uc != UnicodeCategory.NonSpacingMark) + { + sb.Append(stFormD[ich]); + } + } + + return sb.ToString().Normalize(NormalizationForm.FormC); + } + + protected string ApplyReplacements(string str) + { + //perf: don't use string builder here, it's faster without + foreach (var replacement in _config.StringReplacements) + { + str = str.Replace(replacement.Key, replacement.Value); + } + + return str; + } + + protected string DeleteCharacters(string str) + { + return _deniedCharactersRegex.Replace(str, string.Empty); + } + } +} + diff --git a/src/Slugify.Core/Slugify.Core.csproj b/src/Slugify.Core/Slugify.Core.csproj index f83b66f..ef095dd 100644 --- a/src/Slugify.Core/Slugify.Core.csproj +++ b/src/Slugify.Core/Slugify.Core.csproj @@ -35,6 +35,7 @@ With default settings, you will get an hyphenized, lowercase, alphanumeric versi runtime; build; native; contentfiles; analyzers; buildtransitive
+ diff --git a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md index d325c40..8c58301 100644 --- a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md +++ b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report-github.md @@ -8,10 +8,7 @@ Intel Core i9-9900K CPU 3.60GHz (Coffee Lake), 1 CPU, 16 logical and 8 physical ``` -| Method | N | word | Mean | Error | StdDev | Ratio | RatioSD | Gen 0 | Gen 1 | Gen 2 | Allocated | -|--------- |-- |--------------------- |-----------:|---------:|---------:|------:|--------:|-------:|------:|------:|----------:| -| **Baseline** | **1** | **Hello** | **660.0 ns** | **2.01 ns** | **1.78 ns** | **1.00** | **0.00** | **0.0734** | **-** | **-** | **616 B** | -| Improved | 1 | Hello | 643.8 ns | 12.74 ns | 11.92 ns | 0.98 | 0.02 | 0.0553 | - | - | 464 B | -| | | | | | | | | | | | | -| **Baseline** | **1** | **lorem(...)oot!! [40]** | **4,174.1 ns** | **11.46 ns** | **10.72 ns** | **1.00** | **0.00** | **0.4501** | **-** | **-** | **3824 B** | -| Improved | 1 | lorem(...)oot!! [40] | 3,924.9 ns | 7.03 ns | 5.87 ns | 0.94 | 0.00 | 0.3967 | - | - | 3360 B | +| Method | Mean | Error | StdDev | Ratio | Gen 0 | Gen 1 | Gen 2 | Allocated | +|--------- |---------:|---------:|---------:|------:|----------:|------:|------:|----------:| +| Baseline | 42.32 ms | 0.045 ms | 0.040 ms | 1.00 | 3750.0000 | - | - | 30.57 MB | +| Improved | 26.14 ms | 0.323 ms | 0.287 ms | 0.62 | 2562.5000 | - | - | 20.6 MB | diff --git a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv index 7e5a40e..0ad5aaf 100644 --- a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv +++ b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.csv @@ -1,5 +1,3 @@ -Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,N,word,Mean,Error,StdDev,Ratio,RatioSD,Gen 0,Gen 1,Gen 2,Allocated -Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,Hello,660.0 ns,2.01 ns,1.78 ns,1.00,0.00,0.0734,0.0000,0.0000,616 B -Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,Hello,643.8 ns,12.74 ns,11.92 ns,0.98,0.02,0.0553,0.0000,0.0000,464 B -Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,lorem(...)oot!! [40],"4,174.1 ns",11.46 ns,10.72 ns,1.00,0.00,0.4501,0.0000,0.0000,3824 B -Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,1,lorem(...)oot!! [40],"3,924.9 ns",7.03 ns,5.87 ns,0.94,0.00,0.3967,0.0000,0.0000,3360 B +Method,Job,AnalyzeLaunchVariance,EvaluateOverhead,MaxAbsoluteError,MaxRelativeError,MinInvokeCount,MinIterationTime,OutlierMode,Affinity,EnvironmentVariables,Jit,Platform,PowerPlanMode,Runtime,AllowVeryLargeObjects,Concurrent,CpuGroups,Force,HeapAffinitizeMask,HeapCount,NoAffinitize,RetainVm,Server,Arguments,BuildConfiguration,Clock,EngineFactory,NuGetReferences,Toolchain,IsMutator,InvocationCount,IterationCount,IterationTime,LaunchCount,MaxIterationCount,MaxWarmupIterationCount,MinIterationCount,MinWarmupIterationCount,RunStrategy,UnrollFactor,WarmupCount,Mean,Error,StdDev,Ratio,Gen 0,Gen 1,Gen 2,Allocated +Baseline,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,42.32 ms,0.045 ms,0.040 ms,1.00,3750.0000,0.0000,0.0000,30.57 MB +Improved,DefaultJob,False,Default,Default,Default,Default,Default,Default,1111111111111111,Empty,RyuJit,X64,8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c,.NET Core 3.1,False,True,False,True,Default,Default,False,False,False,Default,Default,Default,Default,Default,Default,Default,1,Default,Default,Default,Default,Default,Default,Default,Default,16,Default,26.14 ms,0.323 ms,0.287 ms,0.62,2562.5000,0.0000,0.0000,20.6 MB diff --git a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html index 8a6fede..21b55c3 100644 --- a/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html +++ b/tests/Slugify.Core.Benchmarks/BenchmarkDotNet.Artifacts/results/Slugify.Core.Benchmarks.SlugifyBenchmarks-report.html @@ -2,7 +2,7 @@ -Slugify.Core.Benchmarks.SlugifyBenchmarks-20200430-160656 +Slugify.Core.Benchmarks.SlugifyBenchmarks-20200430-175237