From 1eda69629d2556bea8a4c178fb0afd0c7e8614ab Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 21 Jun 2026 14:26:16 +0200 Subject: [PATCH 01/15] =?UTF-8?q?=F0=9F=90=9B=20Fix=20deploy=20job=20gatin?= =?UTF-8?q?g=20when=20optional=20test=20matrices=20are=20skipped?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deploy was being skipped when optional test_mac matrix was disabled in workflow_dispatch, due to skipped-ancestor propagation. Now explicitly gate deploy on direct dependency success only, so both manual workflow runs trigger deployment regardless of macOS test matrix configuration. --- .github/workflows/ci-pipeline.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 23e7af1b..809a4154 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -381,7 +381,8 @@ jobs: security-events: write deploy: - if: github.event_name != 'pull_request' + # Avoid skipped optional jobs (for example disabled macOS matrix runs) from suppressing deployment. + if: ${{ always() && github.event_name != 'pull_request' && needs.build.result == 'success' && needs.pack.result == 'success' && needs.test_qualitygate.result == 'success' && needs.sonarcloud.result == 'success' && needs.codecov.result == 'success' && needs.codeql.result == 'success' }} name: call-nuget needs: [build, pack, test_qualitygate, sonarcloud, codecov, codeql] uses: codebeltnet/jobs-nuget-push/.github/workflows/default.yml@v3 From b34cf4d5536355daccd995585925eb9ae7bcd330 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 21 Jun 2026 15:59:08 +0200 Subject: [PATCH 02/15] =?UTF-8?q?=F0=9F=94=A7=20update=20permissions=20and?= =?UTF-8?q?=20secrets=20in=20CI=20pipeline=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-pipeline.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 809a4154..996ef688 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -393,5 +393,6 @@ jobs: permissions: contents: write packages: write + id-token: write secrets: - NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} + NUGET_USER: ${{ secrets.NUGET_USER }} From b56c663adc7f1907f5fe9820089eb9f5a92568c6 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Sun, 21 Jun 2026 16:10:40 +0200 Subject: [PATCH 03/15] =?UTF-8?q?=F0=9F=94=A7=20update=20permissions=20for?= =?UTF-8?q?=20actions=20and=20contents=20in=20CI=20pipeline?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-pipeline.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index 996ef688..ac24f59a 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -391,7 +391,8 @@ jobs: environment: Production configuration: ${{ inputs.configuration == '' && 'Release' || inputs.configuration }} permissions: - contents: write + actions: read + contents: read packages: write id-token: write secrets: From bc9da5123fd205bcc5e99df42712941110398735 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 20:43:03 +0200 Subject: [PATCH 04/15] =?UTF-8?q?=E2=AC=86=EF=B8=8F=20upgrade=20dependenci?= =?UTF-8?q?es=20to=20latest=20versions?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Update package versions across all target frameworks: Codebelt extensions to 11.1.1, Microsoft.NET.Test.SDK to 18.8.1, and framework-specific packages to latest patch versions. Maintains compatibility across net9.0, net10.0, and netstandard2.0. --- Directory.Packages.props | 46 ++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/Directory.Packages.props b/Directory.Packages.props index d786b422..0c57b9ac 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -6,12 +6,12 @@ - - - - + + + + - + @@ -22,33 +22,33 @@ - + - - - - - + + + + + - + - - - - - + + + + + - - - - - + + + + + - + \ No newline at end of file From 27e10fef7431660669a2ea77ceba74b9d2822ee3 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 20:43:07 +0200 Subject: [PATCH 05/15] =?UTF-8?q?=F0=9F=94=A7=20update=20docfx=20dockerfil?= =?UTF-8?q?e=20configuration?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align DocFX build infrastructure with latest tooling requirements and best practices. --- .docfx/Dockerfile.docfx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.docfx/Dockerfile.docfx b/.docfx/Dockerfile.docfx index 23e1b508..7d97dde5 100644 --- a/.docfx/Dockerfile.docfx +++ b/.docfx/Dockerfile.docfx @@ -1,4 +1,4 @@ -ARG NGINX_VERSION=1.31.1-alpine +ARG NGINX_VERSION=1.31-alpine FROM --platform=$BUILDPLATFORM nginx:${NGINX_VERSION} AS base RUN rm -rf /usr/share/nginx/html/* From aeca6b5f99a5dd0568afd08f45b7931a609a1453 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 20:43:13 +0200 Subject: [PATCH 06/15] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20optimize=20Condition?= =?UTF-8?q?=20validation=20performance?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce net9.0+ optimizations using Span and System.Buffers.Text.Base64 for improved performance on modern runtimes. Refactor algorithms to eliminate allocations in hot paths: IsWhiteSpace, IsBinaryDigits, and IsHexadecimal now use direct iteration. Optimize HasDifference with bitmap-based character tracking for net9.0+ while maintaining netstandard2.0 compatibility. Update corresponding tests to verify optimizations. --- src/Cuemon.Kernel/Condition.cs | 100 +++++++++-- test/Cuemon.Kernel.Tests/ConditionTest.cs | 202 ++++++++++++++++++++++ 2 files changed, 289 insertions(+), 13 deletions(-) diff --git a/src/Cuemon.Kernel/Condition.cs b/src/Cuemon.Kernel/Condition.cs index b2e5713c..d7033ea6 100644 --- a/src/Cuemon.Kernel/Condition.cs +++ b/src/Cuemon.Kernel/Condition.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using System.ComponentModel; using System.Globalization; -using System.IO; using System.Linq; using System.Reflection; using System.Text.RegularExpressions; @@ -279,7 +278,11 @@ public static bool HasConsecutiveCharacters(string value, char character, int le public static bool IsBase64(string value) { if (string.IsNullOrEmpty(value)) { return false; } +#if NET9_0_OR_GREATER + return System.Buffers.Text.Base64.IsValid(value.AsSpan()); +#else return Patterns.TryInvoke(() => Convert.FromBase64String(value), out _); +#endif } /// @@ -290,7 +293,12 @@ public static bool IsBase64(string value) public static bool IsBinaryDigits(string value) { if (string.IsNullOrWhiteSpace(value)) { return false; } - return !value.Any(ch => ch < '0' || ch > '1'); + for (var i = 0; i < value.Length; i++) + { + var character = value[i]; + if (character < '0' || character > '1') { return false; } + } + return true; } /// @@ -360,7 +368,7 @@ public static bool IsDefault(T value) public static bool IsEmailAddress(string value) { if (string.IsNullOrWhiteSpace(value)) { return false; } - return (RegExEmailAddressValidator.Match(value).Length > 0); + return RegExEmailAddressValidator.IsMatch(value); } /// @@ -389,8 +397,8 @@ public static bool IsEnum(string value, Action setup = nul try { var options = Patterns.Configure(setup); + if (!Enum.TryParse(value, options.IgnoreCase, out var result)) { return false; } var hasFlags = enumType.GetTypeInfo().IsDefined(typeof(FlagsAttribute), false); - var result = Enum.Parse(enumType, value, options.IgnoreCase); if (hasFlags && value.IndexOf(',') != -1) { return true; } return Enum.IsDefined(enumType, result); } @@ -490,15 +498,9 @@ public static bool IsHex(string value) { if (string.IsNullOrEmpty(value)) { return false; } if (!IsEven(value.Length)) { return false; } - using (var reader = new StringReader(value)) + for (var i = 0; i < value.Length; i++) { - var even = value.Length / 2; - for (var i = 0; i < even; ++i) - { - var char1 = (char)reader.Read(); - var char2 = (char)reader.Read(); - if (!IsHexDigit(char1) || !IsHexDigit(char2)) { return false; } - } + if (!IsHexDigit(value[i])) { return false; } } return true; } @@ -730,7 +732,11 @@ public static bool IsUri(string value, Action setup = null) public static bool IsWhiteSpace(string value) { if (value is null) { return false; } - return value.All(char.IsWhiteSpace); + for (var i = 0; i < value.Length; i++) + { + if (!char.IsWhiteSpace(value[i])) { return false; } + } + return true; } /// @@ -879,9 +885,77 @@ public static bool HasDifference(string first, string second, out string differe { first ??= string.Empty; second ??= string.Empty; +#if NET9_0_OR_GREATER + return HasDifferenceCore(first, second, out difference); +#else difference = string.Concat(second.Except(first)); return difference.Length != 0; +#endif + } + +#if NET9_0_OR_GREATER + private static bool HasDifferenceCore(string first, string second, out string difference) + { + if (second.Length == 0) + { + difference = string.Empty; + return false; + } + + Span firstAscii = stackalloc ulong[4]; // presence bitmap for characters below 256 + firstAscii.Clear(); + var firstHasNonAscii = false; + foreach (var character in first) + { + if (character < 256) { firstAscii[character >> 6] |= 1UL << (character & 63); } + else { firstHasNonAscii = true; } + } + + HashSet firstNonAscii = null; + System.Text.StringBuilder builder = null; + HashSet emitted = null; + foreach (var character in second) + { + bool present; + if (character < 256) + { + present = (firstAscii[character >> 6] & (1UL << (character & 63))) != 0; + } + else if (!firstHasNonAscii) + { + present = false; + } + else + { + firstNonAscii ??= CreateNonAsciiSet(first); + present = firstNonAscii.Contains(character); + } + if (present) { continue; } + + builder ??= new System.Text.StringBuilder(); + emitted ??= new HashSet(); + if (emitted.Add(character)) { builder.Append(character); } + } + + if (builder == null) + { + difference = string.Empty; + return false; + } + difference = builder.ToString(); + return true; + } + + private static HashSet CreateNonAsciiSet(string value) + { + var set = new HashSet(); + foreach (var character in value) + { + if (character >= 256) { set.Add(character); } + } + return set; } +#endif private static bool IsHexDigit(char character) { diff --git a/test/Cuemon.Kernel.Tests/ConditionTest.cs b/test/Cuemon.Kernel.Tests/ConditionTest.cs index 25db80f8..4d617933 100644 --- a/test/Cuemon.Kernel.Tests/ConditionTest.cs +++ b/test/Cuemon.Kernel.Tests/ConditionTest.cs @@ -234,6 +234,36 @@ public void AddressEnumGuidAndUriChecks_ShouldReturnExpectedResults() Assert.False(Condition.IsUri("not a valid uri")); } + [Fact] + public void IsEnum_ShouldPreserveParsingSemantics() + { + // named values + Assert.True(Condition.IsEnum("Monday")); + Assert.False(Condition.IsEnum("NotADay")); + + // case-insensitive names (default) vs case-sensitive + Assert.True(Condition.IsEnum("monday")); + Assert.False(Condition.IsEnum("monday", o => o.IgnoreCase = false)); + Assert.True(Condition.IsEnum("Monday", o => o.IgnoreCase = false)); + + // numeric values: defined vs undefined + Assert.True(Condition.IsEnum("1")); + Assert.False(Condition.IsEnum("42")); + + // flags and combined flags + Assert.True(Condition.IsEnum("Assembly")); + Assert.True(Condition.IsEnum("Assembly, Module")); + Assert.True(Condition.IsEnum("All")); + + // non-enum generic argument + Assert.False(Condition.IsEnum("1")); + + // null, empty, and whitespace + Assert.False(Condition.IsEnum(null)); + Assert.False(Condition.IsEnum(string.Empty)); + Assert.False(Condition.IsEnum(" ")); + } + [Fact] public void NumericAndRangeChecks_ShouldReturnExpectedResults() { @@ -327,5 +357,177 @@ public void HasDifference_ShouldProvideDifferenceBetweenFirstAndSecond() Assert.Equal("XYZÆØÅ", sut7); Assert.True(sut8); } + + [Fact] + public void HasDifference_ShouldTreatNullAsEmptyString() + { + Assert.False(Condition.HasDifference(null, null, out var bothNull)); + Assert.Equal(string.Empty, bothNull); + + Assert.False(Condition.HasDifference("abc", null, out var secondNull)); + Assert.Equal(string.Empty, secondNull); + + Assert.True(Condition.HasDifference(null, "abc", out var firstNull)); + Assert.Equal("abc", firstNull); + } + + [Fact] + public void HasDifference_ShouldEmitEachDifferenceCharacterOnceInOrderOfSecond() + { + Assert.True(Condition.HasDifference("a", "zzbzbcz", out var difference)); + Assert.Equal("zbc", difference); // duplicates removed, first-occurrence order from second + } + + [Fact] + public void HasDifference_ShouldReportNoDifference_WhenSecondIsSubsetOrReorderedFirst() + { + Assert.False(Condition.HasDifference("abc", "abc", out var equivalent)); + Assert.Equal(string.Empty, equivalent); + + Assert.False(Condition.HasDifference("abc", "cba", out var reordered)); + Assert.Equal(string.Empty, reordered); + + Assert.False(Condition.HasDifference("abc", "aaabbbccc", out var duplicateHeavy)); + Assert.Equal(string.Empty, duplicateHeavy); + + Assert.False(Condition.HasDifference("abc", string.Empty, out var emptySecond)); + Assert.Equal(string.Empty, emptySecond); + } + + [Fact] + public void HasDifference_ShouldDetectDifferenceAtStartMiddleAndEnd() + { + Assert.True(Condition.HasDifference("a", "Zaaaa", out var atStart)); + Assert.Equal("Z", atStart); + + Assert.True(Condition.HasDifference("a", "aaZaa", out var atMiddle)); + Assert.Equal("Z", atMiddle); + + Assert.True(Condition.HasDifference("a", "aaaaZ", out var atEnd)); + Assert.Equal("Z", atEnd); + } + + [Fact] + public void HasDifference_ShouldHandleNonAsciiCharacters() + { + Assert.False(Condition.HasDifference("ÆØÅ", "ÅØÆ", out var noDifference)); + Assert.Equal(string.Empty, noDifference); + + Assert.True(Condition.HasDifference("ÆØ", "ÆØÅÅ", out var difference)); + Assert.Equal("Å", difference); + + // characters outside the Latin-1 range (>= U+0100) + Assert.False(Condition.HasDifference("Ā日本", "本日Ā", out var noDifferenceBmp)); + Assert.Equal(string.Empty, noDifferenceBmp); + + Assert.True(Condition.HasDifference("Ā日", "日Ā本本", out var differenceBmp)); + Assert.Equal("本", differenceBmp); + } + + [Theory] + [InlineData("0AFF", true)] + [InlineData("0aff", true)] + [InlineData("aAbB", true)] + [InlineData("00", true)] + [InlineData("1234567890", true)] + [InlineData("abcdefABCDEF", true)] + [InlineData("0AF", false)] // odd length + [InlineData("0", false)] // odd length + [InlineData("0AGG", false)] // G is not hexadecimal + [InlineData(" 0", false)] // space is not hexadecimal + [InlineData("", false)] // empty + public void IsHex_ShouldPreserveEvenLengthAndDigitSemantics(string value, bool expected) + { + Assert.Equal(expected, Condition.IsHex(value)); + } + + [Theory] + [InlineData("", true)] // empty is treated as consisting only of white-space + [InlineData(" ", true)] + [InlineData(" \t", true)] + [InlineData("\r\n", true)] + [InlineData("\u00A0", true)] // non-breaking space is white-space + [InlineData(" value ", false)] + [InlineData("value", false)] + public void IsWhiteSpace_ShouldPreserveEmptyAndDetectNonWhitespace(string value, bool expected) + { + Assert.Equal(expected, Condition.IsWhiteSpace(value)); + } + + [Fact] + public void IsWhiteSpace_ShouldReturnFalse_WhenNull() + { + Assert.False(Condition.IsWhiteSpace(null)); + } + + [Theory] + [InlineData("0", true)] + [InlineData("1", true)] + [InlineData("101010", true)] + [InlineData("102010", false)] + [InlineData("2", false)] + [InlineData("01 01", false)] // interior space + [InlineData(" ", false)] + [InlineData("", false)] + public void IsBinaryDigits_ShouldValidateOnlyZeroAndOne(string value, bool expected) + { + Assert.Equal(expected, Condition.IsBinaryDigits(value)); + } + + [Fact] + public void IsBinaryDigits_ShouldReturnFalse_WhenNull() + { + Assert.False(Condition.IsBinaryDigits(null)); + } + + [Theory] + [InlineData("user@example.com", true)] + [InlineData("benchmark@cuemon.net", true)] + [InlineData("a@b.co", true)] + [InlineData("MiXeD@CaSe.CoM", true)] // case-insensitive + [InlineData("x@[192.168.0.1]", true)] // IP literal + [InlineData("Ünïcode@example.com", true)] // unanchored: matches embedded ASCII substring + [InlineData("invalid-email", false)] + [InlineData("plain", false)] + [InlineData("café@example.com", false)] // no valid ASCII local part before '@' + [InlineData("Ünïcöde", false)] + [InlineData(" ", false)] + [InlineData("", false)] + public void IsEmailAddress_ShouldValidateAcrossRepresentativeInputs(string value, bool expected) + { + Assert.Equal(expected, Condition.IsEmailAddress(value)); + } + + [Fact] + public void IsEmailAddress_ShouldValidateBoundaryLengthAndNull() + { + Assert.False(Condition.IsEmailAddress(null)); + Assert.True(Condition.IsEmailAddress(new string('a', 240) + "@example.com")); + } + + [Theory] + [InlineData("QQ==", true)] + [InlineData("Q3VlbW9u", true)] + [InlineData("QUJD", true)] + [InlineData("YWJjZA==", true)] + [InlineData("abcd", true)] // unpadded multiple of four + [InlineData(" QQ== ", true)] // surrounding white-space is ignored + [InlineData("Q3Vl\nbW9u", true)] // interior white-space is ignored + [InlineData("QQ=", false)] // malformed length + [InlineData("QQ", false)] // malformed length + [InlineData("QQ=Q", false)] // padding in the middle + [InlineData("****", false)] // invalid characters + [InlineData("DJ BOBO", false)] + [InlineData("", false)] // empty + public void IsBase64_ShouldValidateWhitespacePaddingAndInvalidInputs(string value, bool expected) + { + Assert.Equal(expected, Condition.IsBase64(value)); + } + + [Fact] + public void IsBase64_ShouldReturnFalse_WhenNull() + { + Assert.False(Condition.IsBase64(null)); + } } } From ed6fcab31e5b43f488d991e4a37b86b94bbc1a1d Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 20:43:19 +0200 Subject: [PATCH 07/15] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20optimize=20Validator?= =?UTF-8?q?=20performance=20with=20refactored=20helpers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract interface and type validation logic into dedicated helper methods (ContainsInterfaceCore, ContainsTypeCore) to reduce method overhead. Optimize ContainsAny with net9.0+ Span-based optimizations for string searching with case-insensitive comparisons. Inline null and flag validation checks into helpers to eliminate redundant calls. Restructure error-handling deferred-evaluation patterns to compute error messages only when exceptions are thrown. Update tests to verify optimization and refactoring correctness. --- src/Cuemon.Kernel/Validator.cs | 164 ++++++++++++++++------ test/Cuemon.Kernel.Tests/ValidatorTest.cs | 58 ++++++++ 2 files changed, 182 insertions(+), 40 deletions(-) diff --git a/src/Cuemon.Kernel/Validator.cs b/src/Cuemon.Kernel/Validator.cs index 45b69e41..31a42c6a 100644 --- a/src/Cuemon.Kernel/Validator.cs +++ b/src/Cuemon.Kernel/Validator.cs @@ -653,7 +653,10 @@ public static void ThrowIfNotUri(string argument, UriKind uriKind = UriKind.Abso /// public static void ThrowIfContainsInterface(string typeParamName, params Type[] types) { - ThrowIfContainsInterface(typeParamName, FormattableString.Invariant($"Specified argument is contained within at least one of {nameof(types)}."), types); + if (ContainsInterfaceCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), FormattableString.Invariant($"Specified argument is contained within at least one of {nameof(types)}.")); + } } /// @@ -673,9 +676,10 @@ public static void ThrowIfContainsInterface(string typeParamName, params Type /// public static void ThrowIfContainsInterface(string typeParamName, string message, params Type[] types) { - ThrowIfNull(types); - ThrowIfFalse(types.All(type => type.IsInterface), nameof(types), $"At least one of the specified {nameof(types)} is not an interface."); - if (HasInterfaces(typeof(T), types)) { throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); } + if (ContainsInterfaceCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); + } } /// @@ -698,9 +702,10 @@ public static void ThrowIfContainsInterface(string typeParamName, string mess public static void ThrowIfContainsInterface(Type argument, Type[] types, string message = "Specified argument is contained within at least one of the specified types.", [CallerArgumentExpression(nameof(argument))] string paramName = null) { ThrowIfNull(argument); - ThrowIfNull(types); - ThrowIfFalse(types.All(type => type.IsInterface), nameof(types), $"At least one of the specified {nameof(types)} is not an interface."); - if (HasInterfaces(argument, types)) { throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); } + if (ContainsInterfaceCore(argument, types)) + { + throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); + } } /// @@ -719,7 +724,10 @@ public static void ThrowIfContainsInterface(Type argument, Type[] types, string /// public static void ThrowIfNotContainsInterface(string typeParamName, params Type[] types) { - ThrowIfNotContainsInterface(typeParamName, FormattableString.Invariant($"Specified argument is not contained within at least one of {nameof(types)}."), types); + if (!ContainsInterfaceCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), FormattableString.Invariant($"Specified argument is not contained within at least one of {nameof(types)}.")); + } } /// @@ -739,9 +747,10 @@ public static void ThrowIfNotContainsInterface(string typeParamName, params T /// public static void ThrowIfNotContainsInterface(string typeParamName, string message, params Type[] types) { - ThrowIfNull(types); - ThrowIfFalse(types.All(type => type.IsInterface), nameof(types), $"At least one of the specified {nameof(types)} is not an interface."); - if (!HasInterfaces(typeof(T), types)) { throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); } + if (!ContainsInterfaceCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); + } } /// @@ -764,9 +773,10 @@ public static void ThrowIfNotContainsInterface(string typeParamName, string m public static void ThrowIfNotContainsInterface(Type argument, Type[] types, string message = "Specified argument is not contained within at least one of the specified types.", [CallerArgumentExpression(nameof(argument))] string paramName = null) { ThrowIfNull(argument); - ThrowIfNull(types); - ThrowIfFalse(types.All(type => type.IsInterface), nameof(types), $"At least one of the specified {nameof(types)} is not an interface."); - if (!HasInterfaces(argument, types)) { throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); } + if (!ContainsInterfaceCore(argument, types)) + { + throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); + } } /// @@ -805,8 +815,10 @@ public static void ThrowIfContainsType(object argument, Type[] types, string mes public static void ThrowIfContainsType(Type argument, Type[] types, string message = "Specified argument is contained within at least one of the specified types.", [CallerArgumentExpression(nameof(argument))] string paramName = null) { ThrowIfNull(argument); - ThrowIfNull(types); - if (HasTypes(argument, types)) { throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); } + if (ContainsTypeCore(argument, types)) + { + throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); + } } /// @@ -822,7 +834,10 @@ public static void ThrowIfContainsType(Type argument, Type[] types, string messa /// public static void ThrowIfContainsType(string typeParamName, params Type[] types) { - ThrowIfContainsType(typeParamName, FormattableString.Invariant($"Specified argument is contained within at least one of {nameof(types)}."), types); + if (ContainsTypeCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), FormattableString.Invariant($"Specified argument is contained within at least one of {nameof(types)}.")); + } } /// @@ -839,8 +854,10 @@ public static void ThrowIfContainsType(string typeParamName, params Type[] ty /// public static void ThrowIfContainsType(string typeParamName, string message, params Type[] types) { - ThrowIfNull(types); - if (HasTypes(typeof(T), types)) { throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); } + if (ContainsTypeCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); + } } /// @@ -860,8 +877,10 @@ public static void ThrowIfContainsType(string typeParamName, string message, public static void ThrowIfNotContainsType(Type argument, Type[] types, string message = "Specified argument is not contained within at least one of the specified types.", [CallerArgumentExpression(nameof(argument))] string paramName = null) { ThrowIfNull(argument); - ThrowIfNull(types); - if (!HasTypes(argument, types)) { throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); } + if (!ContainsTypeCore(argument, types)) + { + throw new ArgumentOutOfRangeException(paramName, CreateTypeList(types), message); + } } /// @@ -896,7 +915,10 @@ public static void ThrowIfNotContainsType(object argument, Type[] types, string /// public static void ThrowIfNotContainsType(string typeParamName, params Type[] types) { - ThrowIfNotContainsType(typeParamName, FormattableString.Invariant($"Specified argument is not contained within at least one of {nameof(types)}."), types); + if (!ContainsTypeCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), FormattableString.Invariant($"Specified argument is not contained within at least one of {nameof(types)}.")); + } } /// @@ -913,8 +935,10 @@ public static void ThrowIfNotContainsType(string typeParamName, params Type[] /// public static void ThrowIfNotContainsType(string typeParamName, string message, params Type[] types) { - ThrowIfNull(types); - if (!HasTypes(typeof(T), types)) { throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); } + if (!ContainsTypeCore(typeof(T), types)) + { + throw new TypeArgumentOutOfRangeException(typeParamName, CreateTypeList(types), message); + } } /// @@ -1078,8 +1102,11 @@ public static void ThrowIfContainsReservedKeyword(string argument, IEnumerable public static void ThrowIfDifferent(string first, string second, string paramName, string message = null) { - message ??= FormattableString.Invariant($"Specified arguments has a difference between {nameof(second)} and {nameof(first)}."); - if (Condition.HasDifference(first, second, out var invalidCharacters)) { throw new ArgumentOutOfRangeException(paramName, invalidCharacters, message); } + if (Condition.HasDifference(first, second, out var invalidCharacters)) + { + message ??= FormattableString.Invariant($"Specified arguments has a difference between {nameof(second)} and {nameof(first)}."); + throw new ArgumentOutOfRangeException(paramName, invalidCharacters, message); + } } /// @@ -1094,8 +1121,11 @@ public static void ThrowIfDifferent(string first, string second, string paramNam /// public static void ThrowIfNotDifferent(string first, string second, string paramName, string message = null) { - message ??= FormattableString.Invariant($"Specified arguments does not have a difference between {nameof(second)} and {nameof(first)}."); - if (!Condition.HasDifference(first, second, out _)) { throw new ArgumentOutOfRangeException(paramName, message); } + if (!Condition.HasDifference(first, second, out _)) + { + message ??= FormattableString.Invariant($"Specified arguments does not have a difference between {nameof(second)} and {nameof(first)}."); + throw new ArgumentOutOfRangeException(paramName, message); + } } /// @@ -1114,7 +1144,7 @@ public static void ThrowIfContainsAny(string argument, char[] characters, String ThrowIfNull(characters); if (ContainsAny(argument, characters, comparison)) { - throw new ArgumentOutOfRangeException(paramName, CreateCharacterList(argument.Where(c => characters.Any(find => string.Equals(c.ToString(), find.ToString(), comparison))).Distinct()), message); + throw new ArgumentOutOfRangeException(paramName, CreateMatchingCharacterList(argument, characters, comparison), message); } } @@ -1151,14 +1181,41 @@ public static void ThrowWhen(Action> condi Patterns.CreateInstance(condition); } - private static bool ContainsAny(string argument, IEnumerable characters, StringComparison comparison) + private static bool ContainsAny(string argument, char[] characters, StringComparison comparison) { if (argument == null) { return false; } - foreach (var character in characters) +#if NET9_0_OR_GREATER + var span = argument.AsSpan(); + Span candidate = stackalloc char[1]; + for (var j = 0; j < characters.Length; j++) { - if (argument.IndexOf(character.ToString(), comparison) >= 0) { return true; } + var character = characters[j]; + if (comparison == StringComparison.Ordinal) + { + if (span.IndexOf(character) >= 0) { return true; } + } + else + { + candidate[0] = character; + if (span.IndexOf(candidate, comparison) >= 0) { return true; } + } } return false; +#else + for (var j = 0; j < characters.Length; j++) + { + var character = characters[j]; + if (comparison == StringComparison.Ordinal) + { + if (argument.IndexOf(character) >= 0) { return true; } + } + else if (argument.IndexOf(character.ToString(), comparison) >= 0) + { + return true; + } + } + return false; +#endif } private static string CreateCharacterList(IEnumerable characters) @@ -1166,29 +1223,56 @@ private static string CreateCharacterList(IEnumerable characters) return string.Join(",", characters.Select(c => $"'{c}'")); } + private static string CreateMatchingCharacterList(string argument, char[] characters, StringComparison comparison) + { + return CreateCharacterList(argument.Where(c => characters.Any(find => string.Equals(c.ToString(), find.ToString(), comparison))).Distinct()); + } + private static string CreateTypeList(IEnumerable types) { return string.Join(", ", types.Select(type => ToFriendlyTypeName(type, true))); } - private static bool HasInterfaces(Type source, IEnumerable interfaceTypes) + private static bool ContainsInterfaceCore(Type source, Type[] types) + { + ThrowIfNull(types); + ThrowIfFalse(types.All(type => type.IsInterface), nameof(types), $"At least one of the specified {nameof(types)} is not an interface."); + return HasInterfaces(source, types); + } + + private static bool ContainsTypeCore(Type source, Type[] types) + { + ThrowIfNull(types); + return HasTypes(source, types); + } + + private static bool HasInterfaces(Type source, Type[] interfaceTypes) { - var implementedInterfaces = source.IsInterface ? Enumerable.Repeat(source, 1).Concat(source.GetInterfaces()).ToList() : source.GetInterfaces().ToList(); - foreach (var interfaceType in interfaceTypes.Where(type => type.IsInterface)) + var implementedInterfaces = source.GetInterfaces(); + for (var i = 0; i < interfaceTypes.Length; i++) { - foreach (var implementedInterface in implementedInterfaces) + var interfaceType = interfaceTypes[i]; + if (!interfaceType.IsInterface) { continue; } + if (source.IsInterface && MatchesInterface(source, interfaceType)) { return true; } + for (var j = 0; j < implementedInterfaces.Length; j++) { - if (implementedInterface.IsGenericType && interfaceType == implementedInterface.GetGenericTypeDefinition()) { return true; } - if (interfaceType == implementedInterface) { return true; } + if (MatchesInterface(implementedInterfaces[j], interfaceType)) { return true; } } } return false; } - private static bool HasTypes(Type source, IEnumerable types) + private static bool MatchesInterface(Type implementedInterface, Type interfaceType) + { + if (implementedInterface.IsGenericType && interfaceType == implementedInterface.GetGenericTypeDefinition()) { return true; } + return interfaceType == implementedInterface; + } + + private static bool HasTypes(Type source, Type[] types) { - foreach (var type in types) + for (var i = 0; i < types.Length; i++) { + var type = types[i]; var current = source; while (current != null) { diff --git a/test/Cuemon.Kernel.Tests/ValidatorTest.cs b/test/Cuemon.Kernel.Tests/ValidatorTest.cs index e3b1fe43..392fdc19 100644 --- a/test/Cuemon.Kernel.Tests/ValidatorTest.cs +++ b/test/Cuemon.Kernel.Tests/ValidatorTest.cs @@ -1344,5 +1344,63 @@ public void ThrowIfDifferenceAndUriOverloads_ShouldCoverCustomMessageBranches() Assert.StartsWith("custom", Assert.Throws(() => Validator.ThrowIfUri("https://www.cuemon.net/", UriKind.Absolute, "custom", "paramName")).Message); Assert.StartsWith("custom", Assert.Throws(() => Validator.ThrowIfNotUri("www.cuemon.net", UriKind.Absolute, "custom", "paramName")).Message); } + + [Theory] + [InlineData("Cuemon", "C", StringComparison.Ordinal, true)] // match at beginning + [InlineData("Cuemon", "o", StringComparison.Ordinal, true)] // match in middle + [InlineData("Cuemon", "n", StringComparison.Ordinal, true)] // match at end + [InlineData("Cuemon", "c", StringComparison.Ordinal, false)] // ordinal is case-sensitive + [InlineData("Cuemon", "xyz", StringComparison.Ordinal, false)] // no match + [InlineData("Cuemon", "oo", StringComparison.Ordinal, true)] // duplicate candidates + [InlineData("Cuemon", "", StringComparison.Ordinal, false)] // empty candidate set + [InlineData(null, "a", StringComparison.Ordinal, false)] // null argument + [InlineData("Cuemon", "c", StringComparison.OrdinalIgnoreCase, true)] // case-insensitive hit + [InlineData("Cuemon", "C", StringComparison.OrdinalIgnoreCase, true)] + [InlineData("Cuemon", "xyz", StringComparison.OrdinalIgnoreCase, false)] + [InlineData("Cuemon", "u", StringComparison.CurrentCulture, true)] + [InlineData("Cuemon", "c", StringComparison.CurrentCultureIgnoreCase, true)] + [InlineData("Cuemon", "C", StringComparison.InvariantCulture, true)] + [InlineData("Cuemon", "c", StringComparison.InvariantCultureIgnoreCase, true)] + [InlineData("Ærø", "Æ", StringComparison.Ordinal, true)] // non-ASCII exact + [InlineData("Ærø", "æ", StringComparison.Ordinal, false)] // non-ASCII case-sensitive miss + [InlineData("Ærø", "æ", StringComparison.OrdinalIgnoreCase, true)] // non-ASCII case-insensitive hit + public void ThrowIfContainsAny_ShouldDetectMatchesAcrossPositionsAndComparisons(string argument, string candidates, StringComparison comparison, bool shouldThrow) + { + var characters = candidates.ToCharArray(); + if (shouldThrow) + { + Assert.Throws(() => Validator.ThrowIfContainsAny(argument, characters, comparison)); + } + else + { + Validator.ThrowIfContainsAny(argument, characters, comparison); + } + } + + [Fact] + public void ThrowIfContainsAny_ShouldReportDistinctMatchedCharactersFromArgument() + { + var argument = "Cuemon"; + var duplicates = Assert.Throws(() => + Validator.ThrowIfContainsAny(argument, new[] { 'o', 'o' }, StringComparison.Ordinal)); + Assert.Equal("argument", duplicates.ParamName); + Assert.Equal("'o'", duplicates.ActualValue); + + var caseInsensitive = Assert.Throws(() => + Validator.ThrowIfContainsAny(argument, new[] { 'c' }, StringComparison.OrdinalIgnoreCase)); + Assert.Equal("'C'", caseInsensitive.ActualValue); + } + + [Fact] + public void ThrowIfContainsAny_ShouldNotThrow_WhenCandidateSetEmpty() + { + Validator.ThrowIfContainsAny("Cuemon", Array.Empty()); + } + + [Fact] + public void ThrowIfNotContainsAny_ShouldThrow_WhenCandidateSetEmpty() + { + Assert.Throws(() => Validator.ThrowIfNotContainsAny("Cuemon", Array.Empty())); + } } } From 6ecbd439a9aaaf8fcf9742f352030c23f63f1b5b Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 20:43:25 +0200 Subject: [PATCH 08/15] =?UTF-8?q?=E2=9C=85=20add=20comprehensive=20Kernel?= =?UTF-8?q?=20module=20benchmarks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Introduce Cuemon.Kernel.Benchmarks project with dedicated performance measurement suites for core validation and condition utilities: HasDifferenceBenchmark, ValidatorCoreBenchmark, ValidatorFormatBenchmark, ValidatorMiscBenchmark, ValidatorStringBenchmark, and ValidatorTypeBenchmark. Add benchmark project reference to solution. Benchmarks follow repository conventions with namespace matching Cuemon.Kernel and class names ending with Benchmark. --- Cuemon.slnx | 1 + .../Cuemon.Kernel.Benchmarks.csproj | 11 + .../HasDifferenceBenchmark.cs | 137 +++++++ .../ValidatorCoreBenchmark.cs | 364 ++++++++++++++++++ .../ValidatorFormatBenchmark.cs | 235 +++++++++++ .../ValidatorMiscBenchmark.cs | 123 ++++++ .../ValidatorStringBenchmark.cs | 103 +++++ .../ValidatorTypeBenchmark.cs | 160 ++++++++ 8 files changed, 1134 insertions(+) create mode 100644 tuning/Cuemon.Kernel.Benchmarks/Cuemon.Kernel.Benchmarks.csproj create mode 100644 tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs create mode 100644 tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs create mode 100644 tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs create mode 100644 tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs create mode 100644 tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs create mode 100644 tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs diff --git a/Cuemon.slnx b/Cuemon.slnx index 044f0538..d5e09f61 100644 --- a/Cuemon.slnx +++ b/Cuemon.slnx @@ -92,6 +92,7 @@ + diff --git a/tuning/Cuemon.Kernel.Benchmarks/Cuemon.Kernel.Benchmarks.csproj b/tuning/Cuemon.Kernel.Benchmarks/Cuemon.Kernel.Benchmarks.csproj new file mode 100644 index 00000000..6658abe1 --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/Cuemon.Kernel.Benchmarks.csproj @@ -0,0 +1,11 @@ + + + + Cuemon + + + + + + + diff --git a/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs new file mode 100644 index 00000000..f100d8d1 --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs @@ -0,0 +1,137 @@ +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Cuemon +{ + /// + /// The set of set-difference scenarios exercised by . + /// + public enum DifferenceScenario + { + /// Both strings are identical (no difference, low cardinality). + Equivalent, + + /// Same character set, different ordering (no difference). + Reordered, + + /// Same character set with heavy duplication (no difference). + DuplicateHeavy, + + /// A single differing character at the beginning of second. + DiffAtStart, + + /// A single differing character in the middle of second. + DiffAtMiddle, + + /// A single differing character at the end of second. + DiffAtEnd, + + /// High-cardinality strings that share the same set (no difference). + MostlyUnique + } + + /// + /// Measures directly (without the exception overhead of + /// ) across representative set-difference scenarios and lengths. + /// + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class HasDifferenceBenchmark + { + private string _first = null!; + private string _second = null!; + + /// + /// Gets the length of the strings used in the benchmark. + /// + [Params(16, 256, 4096)] + public int Length { get; set; } + + /// + /// Gets the set-difference scenario used in the benchmark. + /// + [Params( + DifferenceScenario.Equivalent, + DifferenceScenario.Reordered, + DifferenceScenario.DuplicateHeavy, + DifferenceScenario.DiffAtStart, + DifferenceScenario.DiffAtMiddle, + DifferenceScenario.DiffAtEnd, + DifferenceScenario.MostlyUnique)] + public DifferenceScenario Scenario { get; set; } + + /// + /// Builds deterministic inputs for the current scenario and length outside the measured operation. + /// + [GlobalSetup] + public void Setup() + { + switch (Scenario) + { + case DifferenceScenario.Equivalent: + _first = new string('a', Length); + _second = new string('a', Length); + break; + case DifferenceScenario.Reordered: + _first = BuildCycle(Length, "abcd"); + _second = BuildCycle(Length, "dcba"); + break; + case DifferenceScenario.DuplicateHeavy: + _first = "abc"; + _second = BuildBlocks(Length); + break; + case DifferenceScenario.DiffAtStart: + _first = new string('a', Length); + _second = "Z" + new string('a', Length - 1); + break; + case DifferenceScenario.DiffAtMiddle: + _first = new string('a', Length); + _second = new string('a', Length / 2) + "Z" + new string('a', Length - (Length / 2) - 1); + break; + case DifferenceScenario.DiffAtEnd: + _first = new string('a', Length); + _second = new string('a', Length - 1) + "Z"; + break; + case DifferenceScenario.MostlyUnique: + _first = BuildUnique(Length); + _second = BuildUnique(Length); + break; + } + } + + /// + /// Measures the set-difference guard. + /// + [Benchmark(Description = "HasDifference")] + [BenchmarkCategory("Difference")] + public bool HasDifference() + { + return Condition.HasDifference(_first, _second, out _); + } + + private static string BuildCycle(int length, string alphabet) + { + var buffer = new char[length]; + for (var i = 0; i < length; i++) { buffer[i] = alphabet[i % alphabet.Length]; } + return new string(buffer); + } + + private static string BuildBlocks(int length) + { + var buffer = new char[length]; + var third = length / 3; + for (var i = 0; i < length; i++) + { + buffer[i] = i < third ? 'a' : i < third * 2 ? 'b' : 'c'; + } + return new string(buffer); + } + + private static string BuildUnique(int length) + { + var buffer = new char[length]; + for (var i = 0; i < length; i++) { buffer[i] = (char)(0x100 + (i % 4000)); } + return new string(buffer); + } + } +} diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs new file mode 100644 index 00000000..f552b07c --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs @@ -0,0 +1,364 @@ +using System; +using System.Collections.Generic; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; +using Cuemon.Configuration; + +namespace Cuemon +{ + /// + /// Measures the common guard, state, and comparison members of . + /// + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class ValidatorCoreBenchmark + { + private const string ParamName = "argument"; + + private object _firstInstance = null!; + private object _secondInstance = null!; + private Decorator _decorator = null!; + private List _sequence = null!; + private BenchmarkOptions _options = null!; + private Action _checkAction = null!; + private Func _checkFunction = null!; + private Func _truePredicate = null!; + private Action _configureOptions = null!; + + /// + /// Initializes deterministic arguments used by the benchmarks. + /// + [GlobalSetup] + public void Setup() + { + _firstInstance = new object(); + _secondInstance = new object(); + _decorator = Decorator.Enclose(_firstInstance); + _sequence = new List { 42 }; + _options = new BenchmarkOptions(); + _checkAction = DoNothing; + _checkFunction = ReturnFortyTwo; + _truePredicate = ReturnTrue; + _configureOptions = ConfigureOptions; + } + + /// + /// Measures construction of a instance. + /// + [Benchmark(Baseline = true, Description = "Constructor")] + [BenchmarkCategory("Core")] + public Validator Constructor() + { + return new Validator(); + } + + /// + /// Measures access to the singleton. + /// + [Benchmark(Description = "ThrowIf property")] + [BenchmarkCategory("Core")] + public Validator ThrowIf_Property() + { + return Validator.ThrowIf; + } + + /// + /// Measures the action overload of . + /// + [Benchmark(Description = "CheckParameter - action")] + [BenchmarkCategory("Core")] + public object CheckParameter_Action() + { + return Validator.CheckParameter(_firstInstance, _checkAction); + } + + /// + /// Measures the function overload of . + /// + [Benchmark(Description = "CheckParameter - function")] + [BenchmarkCategory("Core")] + public int CheckParameter_Function() + { + return Validator.CheckParameter(_checkFunction); + } + + /// + /// Measures valid configuration through . + /// + [Benchmark(Description = "ThrowIfInvalidConfigurator")] + [BenchmarkCategory("Options")] + public void ThrowIfInvalidConfigurator() + { + Validator.ThrowIfInvalidConfigurator(_configureOptions, out BenchmarkOptions _); + } + + /// + /// Measures the valid-options path of . + /// + [Benchmark(Description = "ThrowIfInvalidOptions")] + [BenchmarkCategory("Options")] + public void ThrowIfInvalidOptions() + { + Validator.ThrowIfInvalidOptions(_options); + } + + /// + /// Measures the valid state path of . + /// + [Benchmark(Description = "ThrowIfInvalidState - valid")] + [BenchmarkCategory("State")] + public void ThrowIfInvalidState_Valid() + { + Validator.ThrowIfInvalidState(false); + } + + /// + /// Measures the object overload of . + /// + [Benchmark(Description = "ThrowIfDisposed - object")] + [BenchmarkCategory("State")] + public void ThrowIfDisposed_Object() + { + Validator.ThrowIfDisposed(false, _firstInstance); + } + + /// + /// Measures the type overload of . + /// + [Benchmark(Description = "ThrowIfDisposed - type")] + [BenchmarkCategory("State")] + public void ThrowIfDisposed_Type() + { + Validator.ThrowIfDisposed(false, typeof(ValidatorCoreBenchmark)); + } + + /// + /// Measures the decorator overload of . + /// + [Benchmark(Description = "ThrowIfNull - decorator")] + [BenchmarkCategory("Null guards")] + public void ThrowIfNull_Decorator() + { + Validator.ThrowIfNull(_decorator, out object _); + } + + /// + /// Measures the object overload of . + /// + [Benchmark(Description = "ThrowIfNull - object")] + [BenchmarkCategory("Null guards")] + public void ThrowIfNull_Object() + { + Validator.ThrowIfNull(_firstInstance); + } + + /// + /// Measures the Boolean overload of . + /// + [Benchmark(Description = "ThrowIfFalse - Boolean")] + [BenchmarkCategory("Boolean guards")] + public void ThrowIfFalse_Boolean() + { + Validator.ThrowIfFalse(true, ParamName); + } + + /// + /// Measures the predicate overload of . + /// + [Benchmark(Description = "ThrowIfFalse - predicate")] + [BenchmarkCategory("Boolean guards")] + public void ThrowIfFalse_Predicate() + { + Validator.ThrowIfFalse(_truePredicate, ParamName); + } + + /// + /// Measures the Boolean overload of . + /// + [Benchmark(Description = "ThrowIfTrue - Boolean")] + [BenchmarkCategory("Boolean guards")] + public void ThrowIfTrue_Boolean() + { + Validator.ThrowIfTrue(false, ParamName); + } + + /// + /// Measures the predicate overload of . + /// + [Benchmark(Description = "ThrowIfTrue - predicate")] + [BenchmarkCategory("Boolean guards")] + public void ThrowIfTrue_Predicate() + { + Validator.ThrowIfTrue(ReturnFalse, ParamName); + } + + /// + /// Measures with a populated sequence. + /// + [Benchmark(Description = "ThrowIfSequenceEmpty")] + [BenchmarkCategory("Collection guards")] + public void ThrowIfSequenceEmpty() + { + Validator.ThrowIfSequenceEmpty(_sequence); + } + + /// + /// Measures with a populated sequence. + /// + [Benchmark(Description = "ThrowIfSequenceNullOrEmpty")] + [BenchmarkCategory("Collection guards")] + public void ThrowIfSequenceNullOrEmpty() + { + Validator.ThrowIfSequenceNullOrEmpty(_sequence); + } + + /// + /// Measures the valid path of . + /// + [Benchmark(Description = "ThrowIfEmpty")] + [BenchmarkCategory("String guards")] + public void ThrowIfEmpty() + { + Validator.ThrowIfEmpty("Cuemon"); + } + + /// + /// Measures the valid path of . + /// + [Benchmark(Description = "ThrowIfWhiteSpace")] + [BenchmarkCategory("String guards")] + public void ThrowIfWhiteSpace() + { + Validator.ThrowIfWhiteSpace("Cuemon"); + } + + /// + /// Measures the valid path of . + /// + [Benchmark(Description = "ThrowIfNullOrEmpty")] + [BenchmarkCategory("String guards")] + public void ThrowIfNullOrEmpty() + { + Validator.ThrowIfNullOrEmpty("Cuemon"); + } + + /// + /// Measures the valid path of . + /// + [Benchmark(Description = "ThrowIfNullOrWhitespace")] + [BenchmarkCategory("String guards")] + public void ThrowIfNullOrWhitespace() + { + Validator.ThrowIfNullOrWhitespace("Cuemon"); + } + + /// + /// Measures with different instances. + /// + [Benchmark(Description = "ThrowIfSame")] + [BenchmarkCategory("Comparison guards")] + public void ThrowIfSame() + { + Validator.ThrowIfSame(_firstInstance, _secondInstance, ParamName); + } + + /// + /// Measures with the same instance. + /// + [Benchmark(Description = "ThrowIfNotSame")] + [BenchmarkCategory("Comparison guards")] + public void ThrowIfNotSame() + { + Validator.ThrowIfNotSame(_firstInstance, _firstInstance, ParamName); + } + + /// + /// Measures with different values. + /// + [Benchmark(Description = "ThrowIfEqual")] + [BenchmarkCategory("Comparison guards")] + public void ThrowIfEqual() + { + Validator.ThrowIfEqual(1, 2, ParamName); + } + + /// + /// Measures with equal values. + /// + [Benchmark(Description = "ThrowIfNotEqual")] + [BenchmarkCategory("Comparison guards")] + public void ThrowIfNotEqual() + { + Validator.ThrowIfNotEqual(1, 1, ParamName); + } + + /// + /// Measures with an in-range value. + /// + [Benchmark(Description = "ThrowIfGreaterThan")] + [BenchmarkCategory("Range guards")] + public void ThrowIfGreaterThan() + { + Validator.ThrowIfGreaterThan(1, 2, ParamName); + } + + /// + /// Measures with an in-range value. + /// + [Benchmark(Description = "ThrowIfGreaterThanOrEqual")] + [BenchmarkCategory("Range guards")] + public void ThrowIfGreaterThanOrEqual() + { + Validator.ThrowIfGreaterThanOrEqual(1, 2, ParamName); + } + + /// + /// Measures with an in-range value. + /// + [Benchmark(Description = "ThrowIfLowerThan")] + [BenchmarkCategory("Range guards")] + public void ThrowIfLowerThan() + { + Validator.ThrowIfLowerThan(2, 1, ParamName); + } + + /// + /// Measures with an in-range value. + /// + [Benchmark(Description = "ThrowIfLowerThanOrEqual")] + [BenchmarkCategory("Range guards")] + public void ThrowIfLowerThanOrEqual() + { + Validator.ThrowIfLowerThanOrEqual(2, 1, ParamName); + } + + private static void ConfigureOptions(BenchmarkOptions options) + { + options.Value = 42; + } + + private static void DoNothing() + { + } + + private static int ReturnFortyTwo() + { + return 42; + } + + private static bool ReturnFalse() + { + return false; + } + + private static bool ReturnTrue() + { + return true; + } + + private sealed class BenchmarkOptions : IParameterObject + { + public int Value { get; set; } + } + } +} diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs new file mode 100644 index 00000000..76d8b96c --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs @@ -0,0 +1,235 @@ +using System; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Cuemon +{ + /// + /// Measures the format-validation members of over their no-throw paths. + /// All inputs are stored in instance fields (initialized in ) so the JIT cannot + /// treat them as compile-time constants and elide the guard. + /// + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class ValidatorFormatBenchmark + { + private const string ParamName = "argument"; + + private string _nonNumeric = null!; + private string _numeric = null!; + private string _nonHex = null!; + private string _hex = null!; + private string _nonEmail = null!; + private string _email = null!; + private string _nonGuid = null!; + private string _guid = null!; + private string _nonUri = null!; + private string _uri = null!; + private string _nonEnum = null!; + private string _enum = null!; + private string _binary = null!; + private string _base64 = null!; + + /// + /// Initializes deterministic inputs used by the benchmarks. + /// + [GlobalSetup] + public void Setup() + { + _nonNumeric = "Cuemon"; + _numeric = "42"; + _nonHex = "Cuemon"; + _hex = "C0DE"; + _nonEmail = "Cuemon"; + _email = "benchmark@cuemon.net"; + _nonGuid = "Cuemon"; + _guid = "8C929A0D-5534-4D33-AE8E-12B2E8B80B9B"; + _nonUri = "not a URI"; + _uri = "https://www.cuemon.net/"; + _nonEnum = "NotADay"; + _enum = nameof(DayOfWeek.Monday); + _binary = "10101010"; + _base64 = "Q3VlbW9u"; + } + + /// + /// Measures with a non-numeric value (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfNumber")] + [BenchmarkCategory("Numeric")] + public void ThrowIfNumber() + { + Validator.ThrowIfNumber(_nonNumeric); + } + + /// + /// Measures with a numeric value. + /// + [Benchmark(Description = "ThrowIfNotNumber")] + [BenchmarkCategory("Numeric")] + public void ThrowIfNotNumber() + { + Validator.ThrowIfNotNumber(_numeric); + } + + /// + /// Measures with non-hexadecimal text (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfHex")] + [BenchmarkCategory("Hexadecimal")] + public void ThrowIfHex() + { + Validator.ThrowIfHex(_nonHex); + } + + /// + /// Measures with hexadecimal text. + /// + [Benchmark(Description = "ThrowIfNotHex")] + [BenchmarkCategory("Hexadecimal")] + public void ThrowIfNotHex() + { + Validator.ThrowIfNotHex(_hex); + } + + /// + /// Measures with non-email text (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfEmailAddress")] + [BenchmarkCategory("Email")] + public void ThrowIfEmailAddress() + { + Validator.ThrowIfEmailAddress(_nonEmail); + } + + /// + /// Measures with an email address. + /// + [Benchmark(Description = "ThrowIfNotEmailAddress")] + [BenchmarkCategory("Email")] + public void ThrowIfNotEmailAddress() + { + Validator.ThrowIfNotEmailAddress(_email); + } + + /// + /// Measures with non-GUID text (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfGuid")] + [BenchmarkCategory("Guid")] + public void ThrowIfGuid() + { + Validator.ThrowIfGuid(_nonGuid); + } + + /// + /// Measures with a D-format GUID. + /// + [Benchmark(Description = "ThrowIfNotGuid")] + [BenchmarkCategory("Guid")] + public void ThrowIfNotGuid() + { + Validator.ThrowIfNotGuid(_guid); + } + + /// + /// Measures with invalid URI text (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfUri")] + [BenchmarkCategory("Uri")] + public void ThrowIfUri() + { + Validator.ThrowIfUri(_nonUri); + } + + /// + /// Measures with an absolute URI. + /// + [Benchmark(Description = "ThrowIfNotUri")] + [BenchmarkCategory("Uri")] + public void ThrowIfNotUri() + { + Validator.ThrowIfNotUri(_uri); + } + + /// + /// Measures with text outside the enumeration (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfEnum")] + [BenchmarkCategory("Enumeration")] + public void ThrowIfEnum() + { + Validator.ThrowIfEnum(_nonEnum); + } + + /// + /// Measures with an enumeration value. + /// + [Benchmark(Description = "ThrowIfNotEnum")] + [BenchmarkCategory("Enumeration")] + public void ThrowIfNotEnum() + { + Validator.ThrowIfNotEnum(_enum); + } + + /// + /// Measures the type overload of . + /// + [Benchmark(Description = "ThrowIfEnumType - type")] + [BenchmarkCategory("Enumeration")] + public void ThrowIfEnumType_Type() + { + Validator.ThrowIfEnumType(typeof(string)); + } + + /// + /// Measures the generic overload of . + /// + [Benchmark(Description = "ThrowIfEnumType - generic")] + [BenchmarkCategory("Enumeration")] + public void ThrowIfEnumType_Generic() + { + Validator.ThrowIfEnumType(ParamName); + } + + /// + /// Measures the generic overload of . + /// + [Benchmark(Description = "ThrowIfNotEnumType - generic")] + [BenchmarkCategory("Enumeration")] + public void ThrowIfNotEnumType_Generic() + { + Validator.ThrowIfNotEnumType(ParamName); + } + + /// + /// Measures the type overload of . + /// + [Benchmark(Description = "ThrowIfNotEnumType - type")] + [BenchmarkCategory("Enumeration")] + public void ThrowIfNotEnumType_Type() + { + Validator.ThrowIfNotEnumType(typeof(DayOfWeek)); + } + + /// + /// Measures with binary digits. + /// + [Benchmark(Description = "ThrowIfNotBinaryDigits")] + [BenchmarkCategory("Binary")] + public void ThrowIfNotBinaryDigits() + { + Validator.ThrowIfNotBinaryDigits(_binary); + } + + /// + /// Measures with Base64 text. + /// + [Benchmark(Description = "ThrowIfNotBase64String")] + [BenchmarkCategory("Base64")] + public void ThrowIfNotBase64String() + { + Validator.ThrowIfNotBase64String(_base64); + } + } +} diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs new file mode 100644 index 00000000..30829554 --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs @@ -0,0 +1,123 @@ +using System; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Cuemon +{ + /// + /// Measures the character, reserved-keyword, and conditional members of . + /// No-throw and throwing scenarios are kept as separate benchmarks; throwing benchmarks swallow the + /// expected so the run is not invalidated. + /// + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class ValidatorMiscBenchmark + { + private const string ParamName = "argument"; + + private string _argument = null!; + private char[] _presentCharacters = null!; + private char[] _absentCharacters = null!; + private string[] _reservedKeywords = null!; + private Action> _emptyExceptionCondition = null!; + + /// + /// Initializes deterministic inputs used by the benchmarks. + /// + [GlobalSetup] + public void Setup() + { + _argument = "Cuemon"; + _presentCharacters = new[] { 'u' }; // 'u' occurs in "Cuemon" + _absentCharacters = new[] { 'x', 'y', 'z' }; // none occur in "Cuemon" + _reservedKeywords = new[] { "class", "namespace" }; + _emptyExceptionCondition = ConfigureWithoutException; + } + + /// + /// Measures the default-comparer reserved-keyword guard (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfContainsReservedKeyword - default comparer")] + [BenchmarkCategory("Reserved keywords")] + public void ThrowIfContainsReservedKeyword_DefaultComparer() + { + Validator.ThrowIfContainsReservedKeyword(_argument, _reservedKeywords); + } + + /// + /// Measures the custom-comparer reserved-keyword guard. + /// + [Benchmark(Description = "ThrowIfContainsReservedKeyword - custom comparer")] + [BenchmarkCategory("Reserved keywords")] + public void ThrowIfContainsReservedKeyword_CustomComparer() + { + Validator.ThrowIfContainsReservedKeyword(_argument, _reservedKeywords, StringComparer.OrdinalIgnoreCase); + } + + /// + /// Measures the no-throw path of (no candidate occurs). + /// + [Benchmark(Baseline = true, Description = "ThrowIfContainsAny - no match")] + [BenchmarkCategory("Character guards")] + public void ThrowIfContainsAny_NoMatch() + { + Validator.ThrowIfContainsAny(_argument, _absentCharacters); + } + + /// + /// Measures the no-throw path of (a candidate occurs). + /// + [Benchmark(Description = "ThrowIfNotContainsAny - match")] + [BenchmarkCategory("Character guards")] + public void ThrowIfNotContainsAny_Match() + { + Validator.ThrowIfNotContainsAny(_argument, _presentCharacters); + } + + /// + /// Measures the throwing path of (a candidate occurs). + /// + [Benchmark(Description = "ThrowIfContainsAny - match (throws)")] + [BenchmarkCategory("Character guards")] + public void ThrowIfContainsAny_Match_Throws() + { + try + { + Validator.ThrowIfContainsAny(_argument, _presentCharacters); + } + catch (ArgumentException) + { + } + } + + /// + /// Measures the throwing path of (no candidate occurs). + /// + [Benchmark(Description = "ThrowIfNotContainsAny - no match (throws)")] + [BenchmarkCategory("Character guards")] + public void ThrowIfNotContainsAny_NoMatch_Throws() + { + try + { + Validator.ThrowIfNotContainsAny(_argument, _absentCharacters); + } + catch (ArgumentException) + { + } + } + + /// + /// Measures when the condition does not create an exception. + /// + [Benchmark(Description = "ThrowWhen")] + [BenchmarkCategory("Conditional guards")] + public void ThrowWhen() + { + Validator.ThrowWhen(_emptyExceptionCondition); + } + + private static void ConfigureWithoutException(ExceptionCondition condition) + { + } + } +} diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs new file mode 100644 index 00000000..eca0ce62 --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs @@ -0,0 +1,103 @@ +using System; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Cuemon +{ + /// + /// Measures the successful (no-throw) string validation paths over representative input lengths. + /// Inputs are stored in instance fields initialized in so the JIT cannot fold + /// the guards away as compile-time constants. + /// + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class ValidatorStringBenchmark + { + private const string ParamName = "argument"; + + private readonly char[] _absentCharacters = { 'x', 'y', 'z' }; + + private string _value = null!; + private string _equivalentValue = null!; + private string _hexadecimalValue = null!; + private string _base64Value = null!; + + /// + /// Gets the length of the strings used in the benchmark. + /// + [Params(16, 256, 4096)] + public int StringLength { get; set; } + + /// + /// Initializes deterministic strings outside the measured operations. + /// + [GlobalSetup] + public void Setup() + { + _value = new string('a', StringLength); + _equivalentValue = new string('a', StringLength); + _hexadecimalValue = new string('A', StringLength); // hexadecimal digits, even length + _base64Value = new string('A', StringLength); // valid base-64 (length is a multiple of four) + } + + /// + /// Measures the successful null, empty, and whitespace guard (group baseline). + /// + [Benchmark(Baseline = true, Description = "ThrowIfNullOrWhitespace - text")] + [BenchmarkCategory("String guards")] + public void ThrowIfNullOrWhitespace_Text() + { + Validator.ThrowIfNullOrWhitespace(_value); + } + + /// + /// Measures a successful character exclusion guard using ordinal comparison. + /// + [Benchmark(Description = "ThrowIfContainsAny - no match (Ordinal)")] + [BenchmarkCategory("String guards")] + public void ThrowIfContainsAny_NoMatch_Ordinal() + { + Validator.ThrowIfContainsAny(_value, _absentCharacters, StringComparison.Ordinal); + } + + /// + /// Measures a successful character exclusion guard using ordinal, case-insensitive comparison. + /// + [Benchmark(Description = "ThrowIfContainsAny - no match (OrdinalIgnoreCase)")] + [BenchmarkCategory("String guards")] + public void ThrowIfContainsAny_NoMatch_OrdinalIgnoreCase() + { + Validator.ThrowIfContainsAny(_value, _absentCharacters, StringComparison.OrdinalIgnoreCase); + } + + /// + /// Measures a successful set-difference guard for equivalent values. + /// + [Benchmark(Description = "ThrowIfDifferent - equivalent values")] + [BenchmarkCategory("String guards")] + public void ThrowIfDifferent_EquivalentValues() + { + Validator.ThrowIfDifferent(_value, _equivalentValue, ParamName); + } + + /// + /// Measures the successful hexadecimal-format guard. + /// + [Benchmark(Description = "ThrowIfNotHex - hexadecimal text")] + [BenchmarkCategory("String guards")] + public void ThrowIfNotHex_HexadecimalText() + { + Validator.ThrowIfNotHex(_hexadecimalValue); + } + + /// + /// Measures the successful base-64 format guard. + /// + [Benchmark(Description = "ThrowIfNotBase64String - base-64 text")] + [BenchmarkCategory("String guards")] + public void ThrowIfNotBase64String_Base64Text() + { + Validator.ThrowIfNotBase64String(_base64Value); + } + } +} diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs new file mode 100644 index 00000000..fb19d105 --- /dev/null +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs @@ -0,0 +1,160 @@ +using System; +using System.IO; +using BenchmarkDotNet.Attributes; +using BenchmarkDotNet.Configs; + +namespace Cuemon +{ + /// + /// Measures the interface and type-members of . + /// + [MemoryDiagnoser] + [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] + public class ValidatorTypeBenchmark + { + private const string ParamName = "argument"; + + private readonly Type[] _baseTypes = { typeof(Exception) }; + private readonly Type[] _interfaceTypes = { typeof(IConvertible) }; + + /// + /// Measures the generic interface inclusion guard. + /// + [Benchmark(Baseline = true, Description = "ThrowIfContainsInterface - generic")] + [BenchmarkCategory("Interface guards")] + public void ThrowIfContainsInterface_Generic() + { + Validator.ThrowIfContainsInterface(ParamName, _interfaceTypes); + } + + /// + /// Measures the generic interface inclusion guard with a custom message. + /// + [Benchmark(Description = "ThrowIfContainsInterface - generic message")] + [BenchmarkCategory("Interface guards")] + public void ThrowIfContainsInterface_GenericMessage() + { + Validator.ThrowIfContainsInterface(ParamName, "message", _interfaceTypes); + } + + /// + /// Measures the type interface inclusion guard. + /// + [Benchmark(Description = "ThrowIfContainsInterface - type")] + [BenchmarkCategory("Interface guards")] + public void ThrowIfContainsInterface_Type() + { + Validator.ThrowIfContainsInterface(typeof(Stream), _interfaceTypes); + } + + /// + /// Measures the generic interface exclusion guard. + /// + [Benchmark(Description = "ThrowIfNotContainsInterface - generic")] + [BenchmarkCategory("Interface guards")] + public void ThrowIfNotContainsInterface_Generic() + { + Validator.ThrowIfNotContainsInterface(ParamName, _interfaceTypes); + } + + /// + /// Measures the generic interface exclusion guard with a custom message. + /// + [Benchmark(Description = "ThrowIfNotContainsInterface - generic message")] + [BenchmarkCategory("Interface guards")] + public void ThrowIfNotContainsInterface_GenericMessage() + { + Validator.ThrowIfNotContainsInterface(ParamName, "message", _interfaceTypes); + } + + /// + /// Measures the type interface exclusion guard. + /// + [Benchmark(Description = "ThrowIfNotContainsInterface - type")] + [BenchmarkCategory("Interface guards")] + public void ThrowIfNotContainsInterface_Type() + { + Validator.ThrowIfNotContainsInterface(typeof(string), _interfaceTypes); + } + + /// + /// Measures the object type inclusion guard. + /// + [Benchmark(Description = "ThrowIfContainsType - object")] + [BenchmarkCategory("Type guards")] + public void ThrowIfContainsType_Object() + { + Validator.ThrowIfContainsType("Cuemon", _baseTypes); + } + + /// + /// Measures the type inclusion guard. + /// + [Benchmark(Description = "ThrowIfContainsType - type")] + [BenchmarkCategory("Type guards")] + public void ThrowIfContainsType_Type() + { + Validator.ThrowIfContainsType(typeof(string), _baseTypes); + } + + /// + /// Measures the generic type inclusion guard. + /// + [Benchmark(Description = "ThrowIfContainsType - generic")] + [BenchmarkCategory("Type guards")] + public void ThrowIfContainsType_Generic() + { + Validator.ThrowIfContainsType(ParamName, _baseTypes); + } + + /// + /// Measures the generic type inclusion guard with a custom message. + /// + [Benchmark(Description = "ThrowIfContainsType - generic message")] + [BenchmarkCategory("Type guards")] + public void ThrowIfContainsType_GenericMessage() + { + Validator.ThrowIfContainsType(ParamName, "message", _baseTypes); + } + + /// + /// Measures the type exclusion guard. + /// + [Benchmark(Description = "ThrowIfNotContainsType - type")] + [BenchmarkCategory("Type guards")] + public void ThrowIfNotContainsType_Type() + { + Validator.ThrowIfNotContainsType(typeof(ArgumentNullException), _baseTypes); + } + + /// + /// Measures the object type exclusion guard. + /// + [Benchmark(Description = "ThrowIfNotContainsType - object")] + [BenchmarkCategory("Type guards")] + public void ThrowIfNotContainsType_Object() + { + Validator.ThrowIfNotContainsType(new ArgumentNullException(), _baseTypes); + } + + /// + /// Measures the generic type exclusion guard. + /// + [Benchmark(Description = "ThrowIfNotContainsType - generic")] + [BenchmarkCategory("Type guards")] + public void ThrowIfNotContainsType_Generic() + { + Validator.ThrowIfNotContainsType(ParamName, _baseTypes); + } + + /// + /// Measures the generic type exclusion guard with a custom message. + /// + [Benchmark(Description = "ThrowIfNotContainsType - generic message")] + [BenchmarkCategory("Type guards")] + public void ThrowIfNotContainsType_GenericMessage() + { + Validator.ThrowIfNotContainsType(ParamName, "message", _baseTypes); + } + } +} From dd714cfb55c453b096c97390e75a7e72bcfb0af0 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 22:10:38 +0200 Subject: [PATCH 09/15] =?UTF-8?q?=E2=9C=85=20add=20comprehensive=20enum=20?= =?UTF-8?q?parsing=20matrix=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend Condition.IsEnum coverage with exhaustive test matrix for diverse enum types including negative values, [Flags] attributes, and non-enum comparisons. Added ValidatorTest enhancements for edge case validation. Tests ensure new Enum.TryParse implementation maintains backward compatibility with legacy Enum.Parse semantics across int, byte, long, and signed variants. --- test/Cuemon.Kernel.Tests/ConditionTest.cs | 125 ++++++++++++++++++++++ test/Cuemon.Kernel.Tests/ValidatorTest.cs | 62 +++++++++++ 2 files changed, 187 insertions(+) diff --git a/test/Cuemon.Kernel.Tests/ConditionTest.cs b/test/Cuemon.Kernel.Tests/ConditionTest.cs index 4d617933..20e700cc 100644 --- a/test/Cuemon.Kernel.Tests/ConditionTest.cs +++ b/test/Cuemon.Kernel.Tests/ConditionTest.cs @@ -264,6 +264,131 @@ public void IsEnum_ShouldPreserveParsingSemantics() Assert.False(Condition.IsEnum(" ")); } + // Enums covering diverse underlying types, negative values, and [Flags] used by the + // legacy-equivalence matrix below. + private enum RegularMatrixEnum { Zero = 0, One = 1, Two = 2, Three = 3 } + + private enum SignedMatrixEnum { Neg = -2, MinusOne = -1, Zero = 0, Pos = 2 } + + private enum ByteMatrixEnum : byte { A = 0, B = 1, C = 200 } + + private enum LongMatrixEnum : long { One = 1, Big = 5000000000 } + + [Flags] + private enum FlagsMatrixEnum { None = 0, Alpha = 1, Beta = 2, Gamma = 4, All = 7 } + + // Faithful reconstruction of the pre-optimization Condition.IsEnum (Enum.Parse based), + // used to prove the optimized Enum.TryParse implementation is behaviorally equivalent. + private static bool LegacyIsEnum(string value, bool ignoreCase) where T : struct, IConvertible + { + if (string.IsNullOrWhiteSpace(value)) { return false; } + var enumType = typeof(T); + if (!enumType.IsEnum) { return false; } + try + { + var hasFlags = enumType.IsDefined(typeof(FlagsAttribute), false); + var result = Enum.Parse(enumType, value, ignoreCase); + if (hasFlags && value.IndexOf(',') != -1) { return true; } + return Enum.IsDefined(enumType, result); + } + catch (Exception e) when (Patterns.IsRecoverableException(e)) + { + return false; + } + } + + private List CollectEnumMismatches(string label, IEnumerable values) where T : struct, IConvertible + { + var mismatches = new List(); + foreach (var value in values) + { + foreach (var ignoreCase in new[] { true, false }) + { + var legacy = LegacyIsEnum(value, ignoreCase); + var current = Condition.IsEnum(value, o => o.IgnoreCase = ignoreCase); + if (legacy != current) + { + mismatches.Add($"{label}: value={(value ?? "")}, ignoreCase={ignoreCase} -> legacy={legacy}, current={current}"); + } + } + } + return mismatches; + } + + [Fact] + public void IsEnum_ShouldMatchLegacyEnumParseSemantics_AcrossGeneratedMatrix() + { + var values = new[] + { + null, "", " ", "\t", " ", + "0", "1", "2", "3", "4", "7", "8", "42", "200", "255", "256", + "-1", "-2", "-3", "5000000000", "99999999999999999999999", + "One", "one", "ONE", "Two", "Alpha", "alpha", "Beta", "Gamma", "All", "None", + "Bogus", "NotADay", "Zero", + "1,2", "1, 2", "Alpha,Beta", "Alpha, Beta", "Alpha, Bogus", "Read, Write", + ",", "1,", ",1", " 1 ", " One ", "Monday", "monday", "Assembly", "Assembly, Module" + }; + + var mismatches = new List(); + mismatches.AddRange(CollectEnumMismatches("RegularMatrixEnum(int)", values)); + mismatches.AddRange(CollectEnumMismatches("SignedMatrixEnum(int,negative)", values)); + mismatches.AddRange(CollectEnumMismatches("ByteMatrixEnum(byte)", values)); + mismatches.AddRange(CollectEnumMismatches("LongMatrixEnum(long)", values)); + mismatches.AddRange(CollectEnumMismatches("FlagsMatrixEnum([Flags])", values)); + mismatches.AddRange(CollectEnumMismatches("DayOfWeek", values)); + mismatches.AddRange(CollectEnumMismatches("AttributeTargets([Flags])", values)); + mismatches.AddRange(CollectEnumMismatches("ConsoleColor", values)); + mismatches.AddRange(CollectEnumMismatches("int(non-enum)", values)); + mismatches.AddRange(CollectEnumMismatches("bool(non-enum)", values)); + mismatches.AddRange(CollectEnumMismatches("char(non-enum)", values)); + + foreach (var mismatch in mismatches) { TestOutput.WriteLine(mismatch); } + Assert.Empty(mismatches); + } + + [Theory] + [InlineData("-2", true)] // defined negative value + [InlineData("-1", true)] // defined negative value + [InlineData("0", true)] // defined + [InlineData("2", true)] // defined + [InlineData("-3", false)] // undefined negative value + [InlineData("1", false)] // in range but undefined + public void IsEnum_ShouldHandleNegativeAndUndefinedNumericValues(string value, bool expected) + { + Assert.Equal(expected, Condition.IsEnum(value)); + } + + [Theory] + [InlineData("200", true)] // defined + [InlineData("255", false)] // within byte range but undefined + [InlineData("256", false)] // overflows the byte underlying type + [InlineData("-1", false)] // negative cannot fit an unsigned byte enum + public void IsEnum_ShouldHandleByteBackedOverflowAndUndefined(string value, bool expected) + { + Assert.Equal(expected, Condition.IsEnum(value)); + } + + [Theory] + [InlineData("99999999999999999999999", false)] // overflows int + [InlineData("5000000000", false)] // overflows int (fits long) + public void IsEnum_ShouldReturnFalse_OnNumericOverflow(string value, bool expected) + { + Assert.Equal(expected, Condition.IsEnum(value)); + } + + [Theory] + [InlineData("All", true)] // single defined combined member + [InlineData("7", true)] // numeric value equal to a defined member (All) + [InlineData("3", false)] // combined numeric without comma, not a single defined member + [InlineData("1,2", false)] // comma-separated NUMERIC flags are not parsed (names only) + [InlineData("Alpha, Beta", true)] // comma-separated flag names + [InlineData("Alpha,Gamma", true)] // comma-separated flag names (no spaces) + [InlineData("Alpha, Bogus", false)] // one name is not defined + public void IsEnum_ShouldHandleCombinedFlagValues(string value, bool expected) + { + Assert.Equal(expected, Condition.IsEnum(value)); + } + [Fact] public void NumericAndRangeChecks_ShouldReturnExpectedResults() { diff --git a/test/Cuemon.Kernel.Tests/ValidatorTest.cs b/test/Cuemon.Kernel.Tests/ValidatorTest.cs index 392fdc19..bf7b3299 100644 --- a/test/Cuemon.Kernel.Tests/ValidatorTest.cs +++ b/test/Cuemon.Kernel.Tests/ValidatorTest.cs @@ -580,6 +580,68 @@ public void ThrowIfNotEnumType_ShouldThrowTypeArgumentException() }); } + [Theory] + [InlineData("Up", true)] // defined name represents the enum + [InlineData("Down", true)] // defined name + [InlineData("1", true)] // defined numeric value (Up) + [InlineData("0", true)] // defined numeric value (Down) + [InlineData("42", false)] // in-range but undefined numeric value + [InlineData("Sideways", false)] // undefined name + [InlineData("99999999999999999999999", false)] // numeric overflow + [InlineData("", false)] // empty + [InlineData(" ", false)] // whitespace + public void ThrowIfEnum_ShouldThrowOnlyWhenValueRepresentsEnum(string value, bool represents) + { + if (represents) + { + var ex = Assert.Throws(() => Validator.ThrowIfEnum(value, paramName: "arg")); + Assert.Equal("arg", ex.ParamName); + Assert.StartsWith("Value represents an enumeration.", ex.Message); + } + else + { + Validator.ThrowIfEnum(value, paramName: "arg"); + } + } + + [Theory] + [InlineData("Up", false)] // valid value -> no throw + [InlineData("1", false)] // defined numeric value -> no throw + [InlineData("42", true)] // undefined numeric value -> throws + [InlineData("Sideways", true)] // undefined name -> throws + [InlineData("99999999999999999999999", true)] // numeric overflow -> throws + [InlineData("", true)] // empty does not represent the enum -> throws + public void ThrowIfNotEnum_ShouldThrowOnlyWhenValueDoesNotRepresentEnum(string value, bool throws) + { + if (throws) + { + var ex = Assert.Throws(() => Validator.ThrowIfNotEnum(value, paramName: "arg")); + Assert.Equal("arg", ex.ParamName); + Assert.StartsWith("Value does not represents an enumeration.", ex.Message); + } + else + { + Validator.ThrowIfNotEnum(value, paramName: "arg"); + } + } + + [Fact] + public void ThrowIfEnum_ShouldThrow_ForCommaSeparatedFlagNames() + { + var ex = Assert.Throws(() => Validator.ThrowIfEnum("Assembly, Module", paramName: "arg")); + Assert.Equal("arg", ex.ParamName); + Assert.StartsWith("Value represents an enumeration.", ex.Message); + } + + [Fact] + public void ThrowIfEnum_ShouldRespectCaseSensitivity() + { + // case-insensitive (default): "up" matches Up -> throws + Assert.Throws(() => Validator.ThrowIfEnum("up")); + // case-sensitive: "up" does not match Up -> no throw + Validator.ThrowIfEnum("up", ignoreCase: false); + } + [Fact] public void ThrowIfEqual_ShouldThrowArgumentOutOfRangeException() { From 9f687f5bd0bd1b0cd969d2416009e51256b5f2db Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 22:11:08 +0200 Subject: [PATCH 10/15] =?UTF-8?q?=E2=9C=85=20optimize=20benchmarks=20with?= =?UTF-8?q?=20warmup=20tuning=20and=20expanded=20coverage?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add [WarmupCount(3)] attribute to all validator benchmarks (HasDifference, ValidatorCore, ValidatorFormat, ValidatorMisc, ValidatorString, ValidatorType) to stabilize measurement accuracy and reduce noise in micro-benchmark results. Include generated GitHub-compatible benchmark reports documenting optimization baseline metrics. --- ...on.HasDifferenceBenchmark-report-github.md | 57 ++++++++++++ ...on.ValidatorCoreBenchmark-report-github.md | 90 +++++++++++++++++++ ....ValidatorFormatBenchmark-report-github.md | 66 ++++++++++++++ ...on.ValidatorMiscBenchmark-report-github.md | 34 +++++++ ....ValidatorStringBenchmark-report-github.md | 56 ++++++++++++ ...on.ValidatorTypeBenchmark-report-github.md | 58 ++++++++++++ .../HasDifferenceBenchmark.cs | 1 + .../ValidatorCoreBenchmark.cs | 1 + .../ValidatorFormatBenchmark.cs | 1 + .../ValidatorMiscBenchmark.cs | 1 + .../ValidatorStringBenchmark.cs | 1 + .../ValidatorTypeBenchmark.cs | 63 +++++++++++++ 12 files changed, 429 insertions(+) create mode 100644 reports/tuning/Cuemon.HasDifferenceBenchmark-report-github.md create mode 100644 reports/tuning/Cuemon.ValidatorCoreBenchmark-report-github.md create mode 100644 reports/tuning/Cuemon.ValidatorFormatBenchmark-report-github.md create mode 100644 reports/tuning/Cuemon.ValidatorMiscBenchmark-report-github.md create mode 100644 reports/tuning/Cuemon.ValidatorStringBenchmark-report-github.md create mode 100644 reports/tuning/Cuemon.ValidatorTypeBenchmark-report-github.md diff --git a/reports/tuning/Cuemon.HasDifferenceBenchmark-report-github.md b/reports/tuning/Cuemon.HasDifferenceBenchmark-report-github.md new file mode 100644 index 00000000..4a337ae4 --- /dev/null +++ b/reports/tuning/Cuemon.HasDifferenceBenchmark-report-github.md @@ -0,0 +1,57 @@ +``` + +BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8737/25H2/2025Update/HudsonValley2) +12th Gen Intel Core i9-12900KF 3.20GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 11.0.100-preview.4.26230.115 + [Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-MTVXEA : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-HYQNZL : .NET 9.0.18 (9.0.18, 9.0.1826.31522), X64 RyuJIT x86-64-v3 + +PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20 +MinIterationCount=15 WarmupCount=3 + +``` +| Method | Runtime | Length | Scenario | Mean | Error | StdDev | Median | Min | Max | Gen0 | Gen1 | Allocated | +|-------------- |---------- |------- |--------------- |-------------:|-------------:|--------------:|-------------:|-------------:|-------------:|-------:|-------:|----------:| +| **HasDifference** | **.NET 10.0** | **16** | **Equivalent** | **29.63 ns** | **0.055 ns** | **0.049 ns** | **29.62 ns** | **29.58 ns** | **29.75 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 16 | Equivalent | 30.14 ns | 0.628 ns | 0.587 ns | 29.91 ns | 29.51 ns | 31.38 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **16** | **Reordered** | **29.96 ns** | **0.399 ns** | **0.333 ns** | **29.79 ns** | **29.68 ns** | **30.76 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 16 | Reordered | 30.48 ns | 0.635 ns | 0.594 ns | 30.31 ns | 29.84 ns | 32.19 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **16** | **DuplicateHeavy** | **11.18 ns** | **0.247 ns** | **0.243 ns** | **11.14 ns** | **10.95 ns** | **11.98 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 16 | DuplicateHeavy | 10.66 ns | 0.259 ns | 0.254 ns | 10.58 ns | 10.44 ns | 11.44 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **16** | **DiffAtStart** | **61.62 ns** | **1.039 ns** | **0.921 ns** | **61.41 ns** | **60.46 ns** | **63.45 ns** | **0.0188** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 16 | DiffAtStart | 61.34 ns | 1.200 ns | 1.179 ns | 61.35 ns | 58.09 ns | 63.73 ns | 0.0187 | - | 296 B | +| **HasDifference** | **.NET 10.0** | **16** | **DiffAtMiddle** | **61.69 ns** | **1.016 ns** | **0.848 ns** | **61.79 ns** | **60.65 ns** | **63.73 ns** | **0.0187** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 16 | DiffAtMiddle | 62.27 ns | 0.573 ns | 0.508 ns | 62.32 ns | 61.41 ns | 63.20 ns | 0.0187 | - | 296 B | +| **HasDifference** | **.NET 10.0** | **16** | **DiffAtEnd** | **63.34 ns** | **0.546 ns** | **0.510 ns** | **63.33 ns** | **62.66 ns** | **64.48 ns** | **0.0188** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 16 | DiffAtEnd | 64.73 ns | 0.577 ns | 0.512 ns | 64.82 ns | 63.69 ns | 65.71 ns | 0.0187 | - | 296 B | +| **HasDifference** | **.NET 10.0** | **16** | **MostlyUnique** | **164.26 ns** | **1.730 ns** | **1.444 ns** | **164.02 ns** | **162.65 ns** | **166.62 ns** | **0.0421** | **-** | **664 B** | +| HasDifference | .NET 9.0 | 16 | MostlyUnique | 185.11 ns | 1.522 ns | 1.349 ns | 185.00 ns | 182.65 ns | 187.78 ns | 0.0423 | - | 664 B | +| **HasDifference** | **.NET 10.0** | **256** | **Equivalent** | **493.56 ns** | **0.601 ns** | **0.469 ns** | **493.65 ns** | **492.78 ns** | **494.09 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 256 | Equivalent | 492.48 ns | 0.374 ns | 0.292 ns | 492.47 ns | 491.87 ns | 492.87 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **256** | **Reordered** | **494.48 ns** | **0.519 ns** | **0.460 ns** | **494.40 ns** | **493.89 ns** | **495.18 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 256 | Reordered | 493.12 ns | 1.425 ns | 1.263 ns | 492.62 ns | 491.60 ns | 495.17 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **256** | **DuplicateHeavy** | **124.25 ns** | **2.342 ns** | **2.405 ns** | **124.57 ns** | **120.35 ns** | **129.00 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 256 | DuplicateHeavy | 118.22 ns | 0.355 ns | 0.332 ns | 118.25 ns | 117.68 ns | 118.74 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **256** | **DiffAtStart** | **537.08 ns** | **1.568 ns** | **1.309 ns** | **536.75 ns** | **535.49 ns** | **540.36 ns** | **0.0173** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 256 | DiffAtStart | 520.63 ns | 1.161 ns | 1.086 ns | 520.65 ns | 519.10 ns | 522.25 ns | 0.0189 | - | 296 B | +| **HasDifference** | **.NET 10.0** | **256** | **DiffAtMiddle** | **596.67 ns** | **4.290 ns** | **4.013 ns** | **597.40 ns** | **587.90 ns** | **602.00 ns** | **0.0168** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 256 | DiffAtMiddle | 545.56 ns | 3.571 ns | 3.340 ns | 545.36 ns | 539.00 ns | 550.91 ns | 0.0176 | - | 296 B | +| **HasDifference** | **.NET 10.0** | **256** | **DiffAtEnd** | **535.93 ns** | **6.062 ns** | **5.671 ns** | **537.03 ns** | **526.99 ns** | **545.36 ns** | **0.0172** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 256 | DiffAtEnd | 530.36 ns | 3.650 ns | 3.236 ns | 530.90 ns | 524.94 ns | 536.12 ns | 0.0171 | - | 296 B | +| **HasDifference** | **.NET 10.0** | **256** | **MostlyUnique** | **2,684.94 ns** | **40.869 ns** | **38.229 ns** | **2,684.82 ns** | **2,630.73 ns** | **2,745.38 ns** | **0.8160** | **0.0215** | **12952 B** | +| HasDifference | .NET 9.0 | 256 | MostlyUnique | 2,817.49 ns | 34.840 ns | 32.589 ns | 2,830.46 ns | 2,758.76 ns | 2,865.28 ns | 0.8212 | 0.0228 | 12952 B | +| **HasDifference** | **.NET 10.0** | **4096** | **Equivalent** | **7,876.05 ns** | **16.417 ns** | **13.709 ns** | **7,873.97 ns** | **7,859.59 ns** | **7,901.70 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 4096 | Equivalent | 7,856.98 ns | 8.910 ns | 7.440 ns | 7,857.84 ns | 7,847.71 ns | 7,871.61 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **4096** | **Reordered** | **7,871.06 ns** | **8.013 ns** | **6.692 ns** | **7,872.37 ns** | **7,861.78 ns** | **7,880.96 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 4096 | Reordered | 7,855.42 ns | 6.838 ns | 6.062 ns | 7,854.88 ns | 7,846.31 ns | 7,866.68 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **4096** | **DuplicateHeavy** | **1,714.30 ns** | **4.995 ns** | **4.428 ns** | **1,714.63 ns** | **1,707.74 ns** | **1,723.22 ns** | **-** | **-** | **-** | +| HasDifference | .NET 9.0 | 4096 | DuplicateHeavy | 1,697.37 ns | 4.575 ns | 4.055 ns | 1,698.92 ns | 1,691.05 ns | 1,702.80 ns | - | - | - | +| **HasDifference** | **.NET 10.0** | **4096** | **DiffAtStart** | **8,235.33 ns** | **45.189 ns** | **40.059 ns** | **8,235.92 ns** | **8,167.80 ns** | **8,301.60 ns** | **-** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 4096 | DiffAtStart | 7,898.97 ns | 18.350 ns | 15.323 ns | 7,901.69 ns | 7,871.24 ns | 7,927.67 ns | - | - | 296 B | +| **HasDifference** | **.NET 10.0** | **4096** | **DiffAtMiddle** | **8,028.09 ns** | **64.858 ns** | **60.668 ns** | **8,011.30 ns** | **7,947.35 ns** | **8,158.36 ns** | **-** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 4096 | DiffAtMiddle | 7,904.49 ns | 12.562 ns | 11.136 ns | 7,906.29 ns | 7,876.43 ns | 7,924.96 ns | - | - | 296 B | +| **HasDifference** | **.NET 10.0** | **4096** | **DiffAtEnd** | **7,911.52 ns** | **23.094 ns** | **20.473 ns** | **7,906.20 ns** | **7,891.26 ns** | **7,954.35 ns** | **-** | **-** | **296 B** | +| HasDifference | .NET 9.0 | 4096 | DiffAtEnd | 7,918.53 ns | 16.922 ns | 14.130 ns | 7,915.00 ns | 7,900.43 ns | 7,948.04 ns | - | - | 296 B | +| **HasDifference** | **.NET 10.0** | **4096** | **MostlyUnique** | **30,124.44 ns** | **597.038 ns** | **558.470 ns** | **29,955.25 ns** | **29,446.96 ns** | **31,279.33 ns** | **7.7975** | **1.6795** | **123504 B** | +| HasDifference | .NET 9.0 | 4096 | MostlyUnique | 43,509.77 ns | 8,995.085 ns | 10,358.753 ns | 43,107.81 ns | 30,969.54 ns | 57,113.05 ns | 7.8125 | 1.6447 | 123504 B | diff --git a/reports/tuning/Cuemon.ValidatorCoreBenchmark-report-github.md b/reports/tuning/Cuemon.ValidatorCoreBenchmark-report-github.md new file mode 100644 index 00000000..3f20d1f5 --- /dev/null +++ b/reports/tuning/Cuemon.ValidatorCoreBenchmark-report-github.md @@ -0,0 +1,90 @@ +``` + +BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8737/25H2/2025Update/HudsonValley2) +12th Gen Intel Core i9-12900KF 3.20GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 11.0.100-preview.4.26230.115 + [Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-MTVXEA : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-HYQNZL : .NET 9.0.18 (9.0.18, 9.0.1826.31522), X64 RyuJIT x86-64-v3 + +PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20 +MinIterationCount=15 WarmupCount=3 + +``` +| Method | Runtime | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|------------------------------ |---------- |-----------:|----------:|----------:|-----------:|-----------:|-----------:|------:|--------:|-------:|----------:|------------:| +| 'ThrowIfFalse - Boolean' | .NET 10.0 | 0.0009 ns | 0.0023 ns | 0.0021 ns | 0.0000 ns | 0.0000 ns | 0.0067 ns | ? | ? | - | - | ? | +| 'ThrowIfFalse - predicate' | .NET 10.0 | 1.4518 ns | 0.0515 ns | 0.0481 ns | 1.4378 ns | 1.4088 ns | 1.5522 ns | ? | ? | - | - | ? | +| 'ThrowIfTrue - Boolean' | .NET 10.0 | 0.0047 ns | 0.0112 ns | 0.0094 ns | 0.0000 ns | 0.0000 ns | 0.0272 ns | ? | ? | - | - | ? | +| 'ThrowIfTrue - predicate' | .NET 10.0 | 1.4287 ns | 0.0064 ns | 0.0050 ns | 1.4299 ns | 1.4176 ns | 1.4343 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| 'ThrowIfFalse - Boolean' | .NET 9.0 | 0.0001 ns | 0.0002 ns | 0.0002 ns | 0.0000 ns | 0.0000 ns | 0.0006 ns | ? | ? | - | - | ? | +| 'ThrowIfFalse - predicate' | .NET 9.0 | 2.0409 ns | 0.0144 ns | 0.0128 ns | 2.0446 ns | 2.0047 ns | 2.0510 ns | ? | ? | - | - | ? | +| 'ThrowIfTrue - Boolean' | .NET 9.0 | 0.0012 ns | 0.0016 ns | 0.0013 ns | 0.0010 ns | 0.0000 ns | 0.0047 ns | ? | ? | - | - | ? | +| 'ThrowIfTrue - predicate' | .NET 9.0 | 1.6382 ns | 0.0113 ns | 0.0105 ns | 1.6401 ns | 1.6112 ns | 1.6498 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfSequenceEmpty | .NET 10.0 | 0.2113 ns | 0.0093 ns | 0.0087 ns | 0.2081 ns | 0.2023 ns | 0.2287 ns | ? | ? | - | - | ? | +| ThrowIfSequenceNullOrEmpty | .NET 10.0 | 0.2172 ns | 0.0134 ns | 0.0126 ns | 0.2181 ns | 0.2036 ns | 0.2440 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfSequenceEmpty | .NET 9.0 | 0.8215 ns | 0.0130 ns | 0.0115 ns | 0.8245 ns | 0.8060 ns | 0.8471 ns | ? | ? | - | - | ? | +| ThrowIfSequenceNullOrEmpty | .NET 9.0 | 1.0223 ns | 0.0154 ns | 0.0136 ns | 1.0205 ns | 0.9999 ns | 1.0473 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfSame | .NET 10.0 | 0.0008 ns | 0.0012 ns | 0.0011 ns | 0.0000 ns | 0.0000 ns | 0.0033 ns | ? | ? | - | - | ? | +| ThrowIfNotSame | .NET 10.0 | 0.0000 ns | 0.0001 ns | 0.0001 ns | 0.0000 ns | 0.0000 ns | 0.0005 ns | ? | ? | - | - | ? | +| ThrowIfEqual | .NET 10.0 | 0.2047 ns | 0.0046 ns | 0.0041 ns | 0.2061 ns | 0.1968 ns | 0.2095 ns | ? | ? | - | - | ? | +| ThrowIfNotEqual | .NET 10.0 | 0.0015 ns | 0.0018 ns | 0.0017 ns | 0.0013 ns | 0.0000 ns | 0.0049 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfSame | .NET 9.0 | 1.0214 ns | 0.0101 ns | 0.0089 ns | 1.0237 ns | 1.0035 ns | 1.0311 ns | ? | ? | - | - | ? | +| ThrowIfNotSame | .NET 9.0 | 0.8193 ns | 0.0114 ns | 0.0101 ns | 0.8229 ns | 0.7977 ns | 0.8326 ns | ? | ? | - | - | ? | +| ThrowIfEqual | .NET 9.0 | 0.8207 ns | 0.0079 ns | 0.0074 ns | 0.8213 ns | 0.7973 ns | 0.8306 ns | ? | ? | - | - | ? | +| ThrowIfNotEqual | .NET 9.0 | 1.0271 ns | 0.0059 ns | 0.0055 ns | 1.0270 ns | 1.0159 ns | 1.0352 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| Constructor | .NET 10.0 | 2.8861 ns | 0.1873 ns | 0.2157 ns | 2.8157 ns | 2.6196 ns | 3.2732 ns | 1.01 | 0.10 | 0.0015 | 24 B | 1.00 | +| 'ThrowIf property' | .NET 10.0 | 0.7834 ns | 0.0436 ns | 0.0408 ns | 0.7789 ns | 0.7030 ns | 0.8309 ns | 0.27 | 0.02 | - | - | 0.00 | +| 'CheckParameter - action' | .NET 10.0 | 2.1364 ns | 0.0328 ns | 0.0291 ns | 2.1472 ns | 2.0662 ns | 2.1695 ns | 0.74 | 0.05 | - | - | 0.00 | +| 'CheckParameter - function' | .NET 10.0 | 1.1941 ns | 0.0061 ns | 0.0054 ns | 1.1933 ns | 1.1856 ns | 1.2051 ns | 0.42 | 0.03 | - | - | 0.00 | +| | | | | | | | | | | | | | +| Constructor | .NET 9.0 | 2.7773 ns | 0.1900 ns | 0.2188 ns | 2.7491 ns | 2.4768 ns | 3.2375 ns | 1.01 | 0.11 | 0.0015 | 24 B | 1.00 | +| 'ThrowIf property' | .NET 9.0 | 0.5976 ns | 0.0172 ns | 0.0161 ns | 0.5971 ns | 0.5715 ns | 0.6280 ns | 0.22 | 0.02 | - | - | 0.00 | +| 'CheckParameter - action' | .NET 9.0 | 2.2499 ns | 0.0226 ns | 0.0200 ns | 2.2503 ns | 2.1952 ns | 2.2783 ns | 0.81 | 0.06 | - | - | 0.00 | +| 'CheckParameter - function' | .NET 9.0 | 1.2386 ns | 0.0100 ns | 0.0084 ns | 1.2404 ns | 1.2141 ns | 1.2470 ns | 0.45 | 0.03 | - | - | 0.00 | +| | | | | | | | | | | | | | +| 'ThrowIfNull - decorator' | .NET 10.0 | 0.4113 ns | 0.0054 ns | 0.0045 ns | 0.4135 ns | 0.4033 ns | 0.4178 ns | ? | ? | - | - | ? | +| 'ThrowIfNull - object' | .NET 10.0 | 0.2025 ns | 0.0049 ns | 0.0044 ns | 0.2044 ns | 0.1931 ns | 0.2069 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| 'ThrowIfNull - decorator' | .NET 9.0 | 8.5274 ns | 0.0357 ns | 0.0316 ns | 8.5215 ns | 8.4763 ns | 8.5915 ns | ? | ? | - | - | ? | +| 'ThrowIfNull - object' | .NET 9.0 | 0.0122 ns | 0.0054 ns | 0.0047 ns | 0.0132 ns | 0.0006 ns | 0.0190 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfInvalidConfigurator | .NET 10.0 | 7.4054 ns | 0.1820 ns | 0.2095 ns | 7.3917 ns | 7.1096 ns | 7.8605 ns | ? | ? | 0.0015 | 24 B | ? | +| ThrowIfInvalidOptions | .NET 10.0 | 1.2375 ns | 0.0168 ns | 0.0157 ns | 1.2410 ns | 1.1848 ns | 1.2535 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfInvalidConfigurator | .NET 9.0 | 10.2685 ns | 0.1600 ns | 0.1497 ns | 10.2251 ns | 10.0541 ns | 10.5256 ns | ? | ? | 0.0015 | 24 B | ? | +| ThrowIfInvalidOptions | .NET 9.0 | 0.8304 ns | 0.0147 ns | 0.0131 ns | 0.8283 ns | 0.8165 ns | 0.8560 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfGreaterThan | .NET 10.0 | 0.0021 ns | 0.0042 ns | 0.0039 ns | 0.0000 ns | 0.0000 ns | 0.0129 ns | ? | ? | - | - | ? | +| ThrowIfGreaterThanOrEqual | .NET 10.0 | 0.0003 ns | 0.0006 ns | 0.0006 ns | 0.0000 ns | 0.0000 ns | 0.0019 ns | ? | ? | - | - | ? | +| ThrowIfLowerThan | .NET 10.0 | 0.0007 ns | 0.0011 ns | 0.0010 ns | 0.0000 ns | 0.0000 ns | 0.0027 ns | ? | ? | - | - | ? | +| ThrowIfLowerThanOrEqual | .NET 10.0 | 0.0002 ns | 0.0005 ns | 0.0005 ns | 0.0000 ns | 0.0000 ns | 0.0019 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfGreaterThan | .NET 9.0 | 0.4234 ns | 0.0187 ns | 0.0175 ns | 0.4137 ns | 0.4089 ns | 0.4605 ns | ? | ? | - | - | ? | +| ThrowIfGreaterThanOrEqual | .NET 9.0 | 0.4364 ns | 0.0284 ns | 0.0266 ns | 0.4288 ns | 0.4100 ns | 0.4946 ns | ? | ? | - | - | ? | +| ThrowIfLowerThan | .NET 9.0 | 0.4056 ns | 0.0089 ns | 0.0079 ns | 0.4058 ns | 0.3948 ns | 0.4210 ns | ? | ? | - | - | ? | +| ThrowIfLowerThanOrEqual | .NET 9.0 | 0.4126 ns | 0.0110 ns | 0.0103 ns | 0.4095 ns | 0.3989 ns | 0.4274 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| 'ThrowIfInvalidState - valid' | .NET 10.0 | 0.0004 ns | 0.0011 ns | 0.0010 ns | 0.0000 ns | 0.0000 ns | 0.0029 ns | ? | ? | - | - | ? | +| 'ThrowIfDisposed - object' | .NET 10.0 | 0.8202 ns | 0.0065 ns | 0.0057 ns | 0.8223 ns | 0.8086 ns | 0.8277 ns | ? | ? | - | - | ? | +| 'ThrowIfDisposed - type' | .NET 10.0 | 0.0007 ns | 0.0009 ns | 0.0008 ns | 0.0006 ns | 0.0000 ns | 0.0028 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| 'ThrowIfInvalidState - valid' | .NET 9.0 | 0.0005 ns | 0.0008 ns | 0.0008 ns | 0.0001 ns | 0.0000 ns | 0.0025 ns | ? | ? | - | - | ? | +| 'ThrowIfDisposed - object' | .NET 9.0 | 1.0207 ns | 0.0060 ns | 0.0047 ns | 1.0231 ns | 1.0077 ns | 1.0238 ns | ? | ? | - | - | ? | +| 'ThrowIfDisposed - type' | .NET 9.0 | 0.0015 ns | 0.0018 ns | 0.0016 ns | 0.0013 ns | 0.0000 ns | 0.0059 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfEmpty | .NET 10.0 | 0.0002 ns | 0.0003 ns | 0.0003 ns | 0.0000 ns | 0.0000 ns | 0.0010 ns | ? | ? | - | - | ? | +| ThrowIfWhiteSpace | .NET 10.0 | 0.2050 ns | 0.0070 ns | 0.0059 ns | 0.2056 ns | 0.1962 ns | 0.2177 ns | ? | ? | - | - | ? | +| ThrowIfNullOrEmpty | .NET 10.0 | 0.0085 ns | 0.0085 ns | 0.0076 ns | 0.0078 ns | 0.0000 ns | 0.0208 ns | ? | ? | - | - | ? | +| ThrowIfNullOrWhitespace | .NET 10.0 | 0.2049 ns | 0.0075 ns | 0.0067 ns | 0.2050 ns | 0.1958 ns | 0.2144 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfEmpty | .NET 9.0 | 0.0016 ns | 0.0032 ns | 0.0030 ns | 0.0000 ns | 0.0000 ns | 0.0108 ns | ? | ? | - | - | ? | +| ThrowIfWhiteSpace | .NET 9.0 | 0.8203 ns | 0.0031 ns | 0.0027 ns | 0.8195 ns | 0.8170 ns | 0.8249 ns | ? | ? | - | - | ? | +| ThrowIfNullOrEmpty | .NET 9.0 | 0.0008 ns | 0.0011 ns | 0.0010 ns | 0.0005 ns | 0.0000 ns | 0.0026 ns | ? | ? | - | - | ? | +| ThrowIfNullOrWhitespace | .NET 9.0 | 0.8230 ns | 0.0032 ns | 0.0028 ns | 0.8222 ns | 0.8184 ns | 0.8283 ns | ? | ? | - | - | ? | diff --git a/reports/tuning/Cuemon.ValidatorFormatBenchmark-report-github.md b/reports/tuning/Cuemon.ValidatorFormatBenchmark-report-github.md new file mode 100644 index 00000000..2d7842e1 --- /dev/null +++ b/reports/tuning/Cuemon.ValidatorFormatBenchmark-report-github.md @@ -0,0 +1,66 @@ +``` + +BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8737/25H2/2025Update/HudsonValley2) +12th Gen Intel Core i9-12900KF 3.20GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 11.0.100-preview.4.26230.115 + [Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-MTVXEA : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-HYQNZL : .NET 9.0.18 (9.0.18, 9.0.1826.31522), X64 RyuJIT x86-64-v3 + +PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20 +MinIterationCount=15 WarmupCount=3 + +``` +| Method | Runtime | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|------------------------------- |---------- |------------:|----------:|----------:|------------:|------------:|------------:|------:|--------:|-------:|----------:|------------:| +| ThrowIfNotBase64String | .NET 10.0 | 2.8934 ns | 0.0103 ns | 0.0092 ns | 2.8946 ns | 2.8770 ns | 2.9081 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfNotBase64String | .NET 9.0 | 2.6816 ns | 0.0212 ns | 0.0177 ns | 2.6844 ns | 2.6520 ns | 2.7142 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfNotBinaryDigits | .NET 10.0 | 2.6126 ns | 0.0193 ns | 0.0171 ns | 2.6095 ns | 2.5913 ns | 2.6493 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfNotBinaryDigits | .NET 9.0 | 2.8414 ns | 0.0182 ns | 0.0161 ns | 2.8443 ns | 2.8037 ns | 2.8622 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| ThrowIfEmailAddress | .NET 10.0 | 114.1496 ns | 1.0902 ns | 0.9104 ns | 114.6724 ns | 112.6790 ns | 115.1337 ns | 1.00 | 0.01 | - | - | NA | +| ThrowIfNotEmailAddress | .NET 10.0 | 99.5773 ns | 0.6011 ns | 0.5020 ns | 99.6990 ns | 98.1583 ns | 100.0400 ns | 0.87 | 0.01 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfEmailAddress | .NET 9.0 | 146.4382 ns | 0.4364 ns | 0.3868 ns | 146.4981 ns | 145.3997 ns | 147.0229 ns | 1.00 | 0.00 | - | - | NA | +| ThrowIfNotEmailAddress | .NET 9.0 | 114.6492 ns | 0.5217 ns | 0.4880 ns | 114.7519 ns | 113.6430 ns | 115.3961 ns | 0.78 | 0.00 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfEnum | .NET 10.0 | 19.6780 ns | 0.3353 ns | 0.2972 ns | 19.6265 ns | 19.1935 ns | 20.2613 ns | 1.00 | 0.02 | 0.0030 | 48 B | 1.00 | +| ThrowIfNotEnum | .NET 10.0 | 62.9211 ns | 0.4876 ns | 0.4561 ns | 62.9361 ns | 61.9052 ns | 63.6236 ns | 3.20 | 0.05 | 0.0043 | 72 B | 1.50 | +| 'ThrowIfEnumType - type' | .NET 10.0 | 0.2194 ns | 0.0105 ns | 0.0098 ns | 0.2210 ns | 0.2061 ns | 0.2415 ns | 0.01 | 0.00 | - | - | 0.00 | +| 'ThrowIfEnumType - generic' | .NET 10.0 | 0.2260 ns | 0.0138 ns | 0.0129 ns | 0.2287 ns | 0.1955 ns | 0.2429 ns | 0.01 | 0.00 | - | - | 0.00 | +| 'ThrowIfNotEnumType - generic' | .NET 10.0 | 0.2158 ns | 0.0112 ns | 0.0105 ns | 0.2126 ns | 0.1990 ns | 0.2313 ns | 0.01 | 0.00 | - | - | 0.00 | +| 'ThrowIfNotEnumType - type' | .NET 10.0 | 0.2162 ns | 0.0085 ns | 0.0066 ns | 0.2192 ns | 0.2031 ns | 0.2223 ns | 0.01 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | | | +| ThrowIfEnum | .NET 9.0 | 23.5041 ns | 0.9247 ns | 1.0278 ns | 23.3222 ns | 22.2512 ns | 26.1332 ns | 1.00 | 0.06 | 0.0071 | 112 B | 1.00 | +| ThrowIfNotEnum | .NET 9.0 | 76.5258 ns | 1.0131 ns | 0.8981 ns | 76.5165 ns | 75.0281 ns | 78.3661 ns | 3.26 | 0.14 | 0.0085 | 136 B | 1.21 | +| 'ThrowIfEnumType - type' | .NET 9.0 | 1.0023 ns | 0.0088 ns | 0.0082 ns | 1.0064 ns | 0.9827 ns | 1.0132 ns | 0.04 | 0.00 | - | - | 0.00 | +| 'ThrowIfEnumType - generic' | .NET 9.0 | 0.8024 ns | 0.0088 ns | 0.0082 ns | 0.8044 ns | 0.7805 ns | 0.8125 ns | 0.03 | 0.00 | - | - | 0.00 | +| 'ThrowIfNotEnumType - generic' | .NET 9.0 | 0.8115 ns | 0.0098 ns | 0.0087 ns | 0.8083 ns | 0.7958 ns | 0.8278 ns | 0.03 | 0.00 | - | - | 0.00 | +| 'ThrowIfNotEnumType - type' | .NET 9.0 | 1.0126 ns | 0.0178 ns | 0.0167 ns | 1.0111 ns | 0.9828 ns | 1.0424 ns | 0.04 | 0.00 | - | - | 0.00 | +| | | | | | | | | | | | | | +| ThrowIfGuid | .NET 10.0 | 2.5814 ns | 0.0263 ns | 0.0246 ns | 2.5715 ns | 2.5380 ns | 2.6331 ns | 1.00 | 0.01 | - | - | NA | +| ThrowIfNotGuid | .NET 10.0 | 13.0563 ns | 0.1379 ns | 0.1289 ns | 13.0234 ns | 12.8819 ns | 13.2565 ns | 5.06 | 0.07 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfGuid | .NET 9.0 | 3.5593 ns | 0.0419 ns | 0.0350 ns | 3.5514 ns | 3.5149 ns | 3.6471 ns | 1.00 | 0.01 | - | - | NA | +| ThrowIfNotGuid | .NET 9.0 | 16.4935 ns | 0.1087 ns | 0.0964 ns | 16.4600 ns | 16.3548 ns | 16.6890 ns | 4.63 | 0.05 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfHex | .NET 10.0 | 0.6292 ns | 0.0106 ns | 0.0100 ns | 0.6292 ns | 0.6012 ns | 0.6431 ns | 1.00 | 0.02 | - | - | NA | +| ThrowIfNotHex | .NET 10.0 | 1.2484 ns | 0.0367 ns | 0.0343 ns | 1.2517 ns | 1.1799 ns | 1.3085 ns | 1.98 | 0.06 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfHex | .NET 9.0 | 1.9705 ns | 0.0228 ns | 0.0202 ns | 1.9605 ns | 1.9466 ns | 2.0186 ns | 1.00 | 0.01 | - | - | NA | +| ThrowIfNotHex | .NET 9.0 | 3.0287 ns | 0.0591 ns | 0.0553 ns | 3.0308 ns | 2.9102 ns | 3.1144 ns | 1.54 | 0.03 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfNumber | .NET 10.0 | 15.3265 ns | 0.1239 ns | 0.1159 ns | 15.3359 ns | 15.1471 ns | 15.5166 ns | 1.00 | 0.01 | - | - | NA | +| ThrowIfNotNumber | .NET 10.0 | 19.2189 ns | 0.1935 ns | 0.1716 ns | 19.1601 ns | 19.0282 ns | 19.6298 ns | 1.25 | 0.01 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfNumber | .NET 9.0 | 20.9156 ns | 0.0847 ns | 0.0792 ns | 20.9219 ns | 20.7625 ns | 21.0299 ns | 1.00 | 0.01 | - | - | NA | +| ThrowIfNotNumber | .NET 9.0 | 25.4723 ns | 0.1644 ns | 0.1538 ns | 25.4569 ns | 25.2596 ns | 25.8007 ns | 1.22 | 0.01 | - | - | NA | +| | | | | | | | | | | | | | +| ThrowIfUri | .NET 10.0 | 78.8806 ns | 2.8760 ns | 3.3120 ns | 78.3785 ns | 74.0347 ns | 87.1510 ns | 1.00 | 0.06 | 0.0204 | 320 B | 1.00 | +| ThrowIfNotUri | .NET 10.0 | 90.3678 ns | 2.2567 ns | 2.5083 ns | 90.6735 ns | 86.8278 ns | 94.7976 ns | 1.15 | 0.06 | 0.0237 | 376 B | 1.18 | +| | | | | | | | | | | | | | +| ThrowIfUri | .NET 9.0 | 88.0244 ns | 2.4042 ns | 2.7687 ns | 88.6392 ns | 82.4452 ns | 91.4258 ns | 1.00 | 0.04 | 0.0201 | 320 B | 1.00 | +| ThrowIfNotUri | .NET 9.0 | 125.3698 ns | 5.3087 ns | 6.1135 ns | 124.5573 ns | 113.6706 ns | 136.7812 ns | 1.43 | 0.08 | 0.0237 | 376 B | 1.18 | diff --git a/reports/tuning/Cuemon.ValidatorMiscBenchmark-report-github.md b/reports/tuning/Cuemon.ValidatorMiscBenchmark-report-github.md new file mode 100644 index 00000000..86818b23 --- /dev/null +++ b/reports/tuning/Cuemon.ValidatorMiscBenchmark-report-github.md @@ -0,0 +1,34 @@ +``` + +BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8737/25H2/2025Update/HudsonValley2) +12th Gen Intel Core i9-12900KF 3.20GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 11.0.100-preview.4.26230.115 + [Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-MTVXEA : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-HYQNZL : .NET 9.0.18 (9.0.18, 9.0.1826.31522), X64 RyuJIT x86-64-v3 + +PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20 +MinIterationCount=15 WarmupCount=3 + +``` +| Method | Runtime | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|---------------------------------------------------- |---------- |-------------:|-----------:|-----------:|-------------:|-------------:|-------------:|-------:|--------:|-------:|----------:|------------:| +| 'ThrowIfContainsAny - no match' | .NET 10.0 | 6.986 ns | 0.0616 ns | 0.0576 ns | 6.964 ns | 6.913 ns | 7.123 ns | 1.00 | 0.01 | - | - | NA | +| 'ThrowIfNotContainsAny - match' | .NET 10.0 | 1.884 ns | 0.0135 ns | 0.0119 ns | 1.886 ns | 1.864 ns | 1.902 ns | 0.27 | 0.00 | - | - | NA | +| 'ThrowIfContainsAny - match (throws)' | .NET 10.0 | 1,354.627 ns | 15.1791 ns | 14.1985 ns | 1,355.466 ns | 1,322.130 ns | 1,377.824 ns | 193.93 | 2.50 | 0.1020 | 1664 B | NA | +| 'ThrowIfNotContainsAny - no match (throws)' | .NET 10.0 | 1,241.701 ns | 10.5299 ns | 9.8497 ns | 1,242.677 ns | 1,213.809 ns | 1,254.369 ns | 177.76 | 1.96 | 0.0443 | 760 B | NA | +| | | | | | | | | | | | | | +| 'ThrowIfContainsAny - no match' | .NET 9.0 | 17.115 ns | 0.0488 ns | 0.0408 ns | 17.128 ns | 17.041 ns | 17.164 ns | 1.00 | 0.00 | - | - | NA | +| 'ThrowIfNotContainsAny - match' | .NET 9.0 | 5.549 ns | 0.0214 ns | 0.0190 ns | 5.552 ns | 5.510 ns | 5.583 ns | 0.32 | 0.00 | - | - | NA | +| 'ThrowIfContainsAny - match (throws)' | .NET 9.0 | 1,945.985 ns | 32.3847 ns | 30.2927 ns | 1,934.675 ns | 1,910.775 ns | 2,022.311 ns | 113.70 | 1.73 | 0.1007 | 1664 B | NA | +| 'ThrowIfNotContainsAny - no match (throws)' | .NET 9.0 | 1,950.613 ns | 19.7315 ns | 18.4569 ns | 1,945.772 ns | 1,920.392 ns | 1,984.450 ns | 113.97 | 1.08 | 0.0469 | 760 B | NA | +| | | | | | | | | | | | | | +| ThrowWhen | .NET 10.0 | 6.329 ns | 0.2048 ns | 0.2358 ns | 6.366 ns | 5.838 ns | 6.670 ns | ? | ? | 0.0015 | 24 B | ? | +| | | | | | | | | | | | | | +| ThrowWhen | .NET 9.0 | 9.314 ns | 0.1063 ns | 0.0942 ns | 9.302 ns | 9.151 ns | 9.495 ns | ? | ? | 0.0015 | 24 B | ? | +| | | | | | | | | | | | | | +| 'ThrowIfContainsReservedKeyword - default comparer' | .NET 10.0 | 4.541 ns | 0.0322 ns | 0.0269 ns | 4.531 ns | 4.502 ns | 4.586 ns | 1.00 | 0.01 | - | - | NA | +| 'ThrowIfContainsReservedKeyword - custom comparer' | .NET 10.0 | 4.115 ns | 0.0158 ns | 0.0140 ns | 4.110 ns | 4.096 ns | 4.139 ns | 0.91 | 0.01 | - | - | NA | +| | | | | | | | | | | | | | +| 'ThrowIfContainsReservedKeyword - default comparer' | .NET 9.0 | 5.457 ns | 0.0461 ns | 0.0431 ns | 5.473 ns | 5.378 ns | 5.511 ns | 1.00 | 0.01 | - | - | NA | +| 'ThrowIfContainsReservedKeyword - custom comparer' | .NET 9.0 | 5.936 ns | 0.0334 ns | 0.0296 ns | 5.934 ns | 5.885 ns | 5.987 ns | 1.09 | 0.01 | - | - | NA | diff --git a/reports/tuning/Cuemon.ValidatorStringBenchmark-report-github.md b/reports/tuning/Cuemon.ValidatorStringBenchmark-report-github.md new file mode 100644 index 00000000..83f0a6dc --- /dev/null +++ b/reports/tuning/Cuemon.ValidatorStringBenchmark-report-github.md @@ -0,0 +1,56 @@ +``` + +BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8737/25H2/2025Update/HudsonValley2) +12th Gen Intel Core i9-12900KF 3.20GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 11.0.100-preview.4.26230.115 + [Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-MTVXEA : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-HYQNZL : .NET 9.0.18 (9.0.18, 9.0.1826.31522), X64 RyuJIT x86-64-v3 + +PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20 +MinIterationCount=15 WarmupCount=3 + +``` +| Method | Runtime | StringLength | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Allocated | Alloc Ratio | +|---------------------------------------------------- |---------- |------------- |--------------:|-----------:|-----------:|--------------:|--------------:|--------------:|----------:|---------:|----------:|------------:| +| **'ThrowIfNullOrWhitespace - text'** | **.NET 10.0** | **16** | **0.2090 ns** | **0.0081 ns** | **0.0072 ns** | **0.2100 ns** | **0.1960 ns** | **0.2232 ns** | **1.00** | **0.05** | **-** | **NA** | +| 'ThrowIfContainsAny - no match (Ordinal)' | .NET 10.0 | 16 | 3.8545 ns | 0.0391 ns | 0.0366 ns | 3.8639 ns | 3.7861 ns | 3.9058 ns | 18.46 | 0.64 | - | NA | +| 'ThrowIfContainsAny - no match (OrdinalIgnoreCase)' | .NET 10.0 | 16 | 5.7693 ns | 0.0624 ns | 0.0584 ns | 5.7478 ns | 5.6901 ns | 5.8837 ns | 27.63 | 0.96 | - | NA | +| 'ThrowIfDifferent - equivalent values' | .NET 10.0 | 16 | 30.6741 ns | 0.1957 ns | 0.1831 ns | 30.7397 ns | 30.3970 ns | 30.9082 ns | 146.92 | 4.96 | - | NA | +| 'ThrowIfNotHex - hexadecimal text' | .NET 10.0 | 16 | 6.0493 ns | 0.0747 ns | 0.0624 ns | 6.0375 ns | 5.9675 ns | 6.1874 ns | 28.98 | 1.01 | - | NA | +| 'ThrowIfNotBase64String - base-64 text' | .NET 10.0 | 16 | 3.1983 ns | 0.3948 ns | 0.4388 ns | 2.8952 ns | 2.8690 ns | 4.3662 ns | 15.32 | 2.11 | - | NA | +| | | | | | | | | | | | | | +| 'ThrowIfNullOrWhitespace - text' | .NET 9.0 | 16 | 1.2279 ns | 0.0057 ns | 0.0051 ns | 1.2276 ns | 1.2176 ns | 1.2390 ns | 1.00 | 0.01 | - | NA | +| 'ThrowIfContainsAny - no match (Ordinal)' | .NET 9.0 | 16 | 5.1475 ns | 0.0380 ns | 0.0337 ns | 5.1422 ns | 5.1090 ns | 5.2131 ns | 4.19 | 0.03 | - | NA | +| 'ThrowIfContainsAny - no match (OrdinalIgnoreCase)' | .NET 9.0 | 16 | 15.4126 ns | 0.0755 ns | 0.0630 ns | 15.4270 ns | 15.3050 ns | 15.5037 ns | 12.55 | 0.07 | - | NA | +| 'ThrowIfDifferent - equivalent values' | .NET 9.0 | 16 | 30.0680 ns | 0.0687 ns | 0.0574 ns | 30.0808 ns | 29.9612 ns | 30.1483 ns | 24.49 | 0.11 | - | NA | +| 'ThrowIfNotHex - hexadecimal text' | .NET 9.0 | 16 | 6.7588 ns | 0.0837 ns | 0.0699 ns | 6.7307 ns | 6.6753 ns | 6.9089 ns | 5.50 | 0.06 | - | NA | +| 'ThrowIfNotBase64String - base-64 text' | .NET 9.0 | 16 | 2.4632 ns | 0.0167 ns | 0.0139 ns | 2.4589 ns | 2.4454 ns | 2.4944 ns | 2.01 | 0.01 | - | NA | +| | | | | | | | | | | | | | +| **'ThrowIfNullOrWhitespace - text'** | **.NET 10.0** | **256** | **0.2053 ns** | **0.0164 ns** | **0.0137 ns** | **0.1992 ns** | **0.1854 ns** | **0.2346 ns** | **1.00** | **0.09** | **-** | **NA** | +| 'ThrowIfContainsAny - no match (Ordinal)' | .NET 10.0 | 256 | 14.7533 ns | 0.2636 ns | 0.2589 ns | 14.6884 ns | 14.4309 ns | 15.4377 ns | 72.15 | 4.67 | - | NA | +| 'ThrowIfContainsAny - no match (OrdinalIgnoreCase)' | .NET 10.0 | 256 | 15.8052 ns | 0.0953 ns | 0.0891 ns | 15.8130 ns | 15.6791 ns | 15.9556 ns | 77.29 | 4.85 | - | NA | +| 'ThrowIfDifferent - equivalent values' | .NET 10.0 | 256 | 500.6127 ns | 5.2231 ns | 4.6301 ns | 500.0484 ns | 492.8398 ns | 508.6385 ns | 2,448.09 | 154.60 | - | NA | +| 'ThrowIfNotHex - hexadecimal text' | .NET 10.0 | 256 | 96.6366 ns | 0.6012 ns | 0.4694 ns | 96.6694 ns | 95.6843 ns | 97.5523 ns | 472.57 | 29.64 | - | NA | +| 'ThrowIfNotBase64String - base-64 text' | .NET 10.0 | 256 | 7.1094 ns | 0.0359 ns | 0.0336 ns | 7.1076 ns | 7.0179 ns | 7.1504 ns | 34.77 | 2.18 | - | NA | +| | | | | | | | | | | | | | +| 'ThrowIfNullOrWhitespace - text' | .NET 9.0 | 256 | 1.2236 ns | 0.0075 ns | 0.0066 ns | 1.2241 ns | 1.2050 ns | 1.2329 ns | 1.00 | 0.01 | - | NA | +| 'ThrowIfContainsAny - no match (Ordinal)' | .NET 9.0 | 256 | 13.0390 ns | 0.0984 ns | 0.0872 ns | 13.0467 ns | 12.8598 ns | 13.1827 ns | 10.66 | 0.09 | - | NA | +| 'ThrowIfContainsAny - no match (OrdinalIgnoreCase)' | .NET 9.0 | 256 | 24.4683 ns | 0.0937 ns | 0.0877 ns | 24.4806 ns | 24.3493 ns | 24.6330 ns | 20.00 | 0.13 | - | NA | +| 'ThrowIfDifferent - equivalent values' | .NET 9.0 | 256 | 495.6196 ns | 1.0700 ns | 0.8935 ns | 495.6281 ns | 493.9982 ns | 497.3675 ns | 405.05 | 2.25 | - | NA | +| 'ThrowIfNotHex - hexadecimal text' | .NET 9.0 | 256 | 97.6221 ns | 0.3138 ns | 0.2935 ns | 97.5774 ns | 96.9968 ns | 98.2066 ns | 79.78 | 0.48 | - | NA | +| 'ThrowIfNotBase64String - base-64 text' | .NET 9.0 | 256 | 6.7426 ns | 0.0442 ns | 0.0413 ns | 6.7452 ns | 6.6333 ns | 6.7896 ns | 5.51 | 0.04 | - | NA | +| | | | | | | | | | | | | | +| **'ThrowIfNullOrWhitespace - text'** | **.NET 10.0** | **4096** | **0.2014 ns** | **0.0068 ns** | **0.0057 ns** | **0.2027 ns** | **0.1909 ns** | **0.2080 ns** | **1.00** | **0.04** | **-** | **NA** | +| 'ThrowIfContainsAny - no match (Ordinal)' | .NET 10.0 | 4096 | 178.7936 ns | 2.9975 ns | 2.5031 ns | 177.3768 ns | 176.4823 ns | 184.2122 ns | 888.56 | 27.30 | - | NA | +| 'ThrowIfContainsAny - no match (OrdinalIgnoreCase)' | .NET 10.0 | 4096 | 202.2872 ns | 0.6133 ns | 0.5122 ns | 202.3260 ns | 201.3919 ns | 203.2353 ns | 1,005.32 | 27.86 | - | NA | +| 'ThrowIfDifferent - equivalent values' | .NET 10.0 | 4096 | 7,904.7501 ns | 85.8306 ns | 76.0866 ns | 7,892.1977 ns | 7,757.0875 ns | 8,078.8161 ns | 39,284.79 | 1,144.04 | - | NA | +| 'ThrowIfNotHex - hexadecimal text' | .NET 10.0 | 4096 | 1,366.0532 ns | 5.3093 ns | 4.9663 ns | 1,367.1497 ns | 1,355.2667 ns | 1,372.5650 ns | 6,788.97 | 188.83 | - | NA | +| 'ThrowIfNotBase64String - base-64 text' | .NET 10.0 | 4096 | 97.6195 ns | 0.6136 ns | 0.5124 ns | 97.8061 ns | 96.5087 ns | 98.1168 ns | 485.15 | 13.61 | - | NA | +| | | | | | | | | | | | | | +| 'ThrowIfNullOrWhitespace - text' | .NET 9.0 | 4096 | 1.2299 ns | 0.0121 ns | 0.0113 ns | 1.2321 ns | 1.2063 ns | 1.2470 ns | 1.00 | 0.01 | - | NA | +| 'ThrowIfContainsAny - no match (Ordinal)' | .NET 9.0 | 4096 | 182.8157 ns | 0.2953 ns | 0.2466 ns | 182.7091 ns | 182.5392 ns | 183.3806 ns | 148.65 | 1.34 | - | NA | +| 'ThrowIfContainsAny - no match (OrdinalIgnoreCase)' | .NET 9.0 | 4096 | 214.6854 ns | 1.0387 ns | 0.9716 ns | 214.3181 ns | 213.0358 ns | 216.5681 ns | 174.56 | 1.74 | - | NA | +| 'ThrowIfDifferent - equivalent values' | .NET 9.0 | 4096 | 7,817.4053 ns | 17.8227 ns | 16.6714 ns | 7,812.4374 ns | 7,787.5782 ns | 7,845.9189 ns | 6,356.43 | 58.25 | - | NA | +| 'ThrowIfNotHex - hexadecimal text' | .NET 9.0 | 4096 | 1,365.1147 ns | 4.8334 ns | 4.5211 ns | 1,366.0036 ns | 1,357.2074 ns | 1,373.2712 ns | 1,109.99 | 10.53 | - | NA | +| 'ThrowIfNotBase64String - base-64 text' | .NET 9.0 | 4096 | 95.5167 ns | 0.2984 ns | 0.2492 ns | 95.4892 ns | 95.0800 ns | 96.0121 ns | 77.67 | 0.72 | - | NA | diff --git a/reports/tuning/Cuemon.ValidatorTypeBenchmark-report-github.md b/reports/tuning/Cuemon.ValidatorTypeBenchmark-report-github.md new file mode 100644 index 00000000..69cc25fb --- /dev/null +++ b/reports/tuning/Cuemon.ValidatorTypeBenchmark-report-github.md @@ -0,0 +1,58 @@ +``` + +BenchmarkDotNet v0.15.8, Windows 11 (10.0.26200.8737/25H2/2025Update/HudsonValley2) +12th Gen Intel Core i9-12900KF 3.20GHz, 1 CPU, 24 logical and 16 physical cores +.NET SDK 11.0.100-preview.4.26230.115 + [Host] : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-MTVXEA : .NET 10.0.10 (10.0.10, 10.0.1026.32716), X64 RyuJIT x86-64-v3 + Job-HYQNZL : .NET 9.0.18 (9.0.18, 9.0.1826.31522), X64 RyuJIT x86-64-v3 + +PowerPlanMode=00000000-0000-0000-0000-000000000000 IterationTime=250ms MaxIterationCount=20 +MinIterationCount=15 WarmupCount=3 + +``` +| Method | Runtime | Mean | Error | StdDev | Median | Min | Max | Ratio | RatioSD | Gen0 | Allocated | Alloc Ratio | +|------------------------------------------------ |---------- |----------:|----------:|----------:|----------:|----------:|----------:|------:|--------:|-------:|----------:|------------:| +| 'ContainsInterface - inline params[]' | .NET 10.0 | 15.758 ns | 0.2767 ns | 0.2453 ns | 15.713 ns | 15.487 ns | 16.309 ns | ? | ? | 0.0045 | 72 B | ? | +| 'ContainsInterface - preallocated static[]' | .NET 10.0 | 13.361 ns | 1.0812 ns | 1.2451 ns | 12.966 ns | 12.023 ns | 16.123 ns | ? | ? | 0.0025 | 40 B | ? | +| 'ContainsInterface - non-params Type overload' | .NET 10.0 | 13.014 ns | 1.0050 ns | 1.1573 ns | 12.799 ns | 11.453 ns | 14.979 ns | ? | ? | 0.0025 | 40 B | ? | +| 'NotContainsInterface - inline params[]' | .NET 10.0 | 19.591 ns | 0.8266 ns | 0.8845 ns | 19.665 ns | 18.263 ns | 21.720 ns | ? | ? | 0.0081 | 128 B | ? | +| 'NotContainsInterface - preallocated static[]' | .NET 10.0 | 16.996 ns | 0.7074 ns | 0.8146 ns | 16.600 ns | 16.231 ns | 18.826 ns | ? | ? | 0.0061 | 96 B | ? | +| | | | | | | | | | | | | | +| 'ContainsInterface - inline params[]' | .NET 9.0 | 17.810 ns | 0.3508 ns | 0.3281 ns | 17.881 ns | 17.182 ns | 18.283 ns | ? | ? | 0.0046 | 72 B | ? | +| 'ContainsInterface - preallocated static[]' | .NET 9.0 | 21.419 ns | 2.1929 ns | 2.5253 ns | 21.984 ns | 13.823 ns | 23.604 ns | ? | ? | 0.0025 | 40 B | ? | +| 'ContainsInterface - non-params Type overload' | .NET 9.0 | 20.955 ns | 2.6607 ns | 3.0640 ns | 22.162 ns | 14.612 ns | 23.467 ns | ? | ? | 0.0025 | 40 B | ? | +| 'NotContainsInterface - inline params[]' | .NET 9.0 | 31.210 ns | 3.5800 ns | 4.1227 ns | 33.947 ns | 25.143 ns | 35.325 ns | ? | ? | 0.0081 | 128 B | ? | +| 'NotContainsInterface - preallocated static[]' | .NET 9.0 | 22.214 ns | 0.5246 ns | 0.6042 ns | 22.043 ns | 21.413 ns | 23.457 ns | ? | ? | 0.0061 | 96 B | ? | +| | | | | | | | | | | | | | +| 'ThrowIfContainsInterface - generic' | .NET 10.0 | 13.625 ns | 0.2814 ns | 0.2633 ns | 13.588 ns | 13.142 ns | 14.016 ns | 1.00 | 0.03 | 0.0025 | 40 B | 1.00 | +| 'ThrowIfContainsInterface - generic message' | .NET 10.0 | 14.202 ns | 0.4195 ns | 0.4662 ns | 14.253 ns | 13.497 ns | 15.325 ns | 1.04 | 0.04 | 0.0025 | 40 B | 1.00 | +| 'ThrowIfContainsInterface - type' | .NET 10.0 | 13.965 ns | 0.3482 ns | 0.4010 ns | 13.965 ns | 13.393 ns | 14.767 ns | 1.03 | 0.03 | 0.0025 | 40 B | 1.00 | +| 'ThrowIfNotContainsInterface - generic' | .NET 10.0 | 17.803 ns | 0.3581 ns | 0.3174 ns | 17.881 ns | 17.186 ns | 18.171 ns | 1.31 | 0.03 | 0.0061 | 96 B | 2.40 | +| 'ThrowIfNotContainsInterface - generic message' | .NET 10.0 | 16.879 ns | 0.3609 ns | 0.4011 ns | 16.850 ns | 16.276 ns | 17.719 ns | 1.24 | 0.04 | 0.0061 | 96 B | 2.40 | +| 'ThrowIfNotContainsInterface - type' | .NET 10.0 | 16.819 ns | 0.4873 ns | 0.5214 ns | 16.835 ns | 15.853 ns | 17.719 ns | 1.23 | 0.04 | 0.0061 | 96 B | 2.40 | +| | | | | | | | | | | | | | +| 'ThrowIfContainsInterface - generic' | .NET 9.0 | 14.600 ns | 0.1827 ns | 0.1526 ns | 14.558 ns | 14.382 ns | 14.859 ns | 1.00 | 0.01 | 0.0025 | 40 B | 1.00 | +| 'ThrowIfContainsInterface - generic message' | .NET 9.0 | 13.978 ns | 0.2039 ns | 0.1703 ns | 13.967 ns | 13.722 ns | 14.311 ns | 0.96 | 0.01 | 0.0025 | 40 B | 1.00 | +| 'ThrowIfContainsInterface - type' | .NET 9.0 | 13.253 ns | 0.2068 ns | 0.1615 ns | 13.201 ns | 13.089 ns | 13.670 ns | 0.91 | 0.01 | 0.0025 | 40 B | 1.00 | +| 'ThrowIfNotContainsInterface - generic' | .NET 9.0 | 19.631 ns | 0.2532 ns | 0.1977 ns | 19.638 ns | 19.298 ns | 19.946 ns | 1.34 | 0.02 | 0.0061 | 96 B | 2.40 | +| 'ThrowIfNotContainsInterface - generic message' | .NET 9.0 | 21.053 ns | 0.2632 ns | 0.2462 ns | 21.024 ns | 20.578 ns | 21.618 ns | 1.44 | 0.02 | 0.0061 | 96 B | 2.40 | +| 'ThrowIfNotContainsInterface - type' | .NET 9.0 | 20.713 ns | 0.4220 ns | 0.4145 ns | 20.698 ns | 20.060 ns | 21.509 ns | 1.42 | 0.03 | 0.0061 | 96 B | 2.40 | +| | | | | | | | | | | | | | +| 'ThrowIfContainsType - object' | .NET 10.0 | 9.311 ns | 0.1370 ns | 0.1282 ns | 9.374 ns | 9.125 ns | 9.487 ns | ? | ? | - | - | ? | +| 'ThrowIfContainsType - type' | .NET 10.0 | 11.206 ns | 1.0214 ns | 1.1763 ns | 11.583 ns | 9.417 ns | 13.914 ns | ? | ? | - | - | ? | +| 'ThrowIfContainsType - generic' | .NET 10.0 | 8.812 ns | 0.1120 ns | 0.1047 ns | 8.818 ns | 8.662 ns | 8.965 ns | ? | ? | - | - | ? | +| 'ThrowIfContainsType - generic message' | .NET 10.0 | 9.549 ns | 0.1390 ns | 0.1300 ns | 9.540 ns | 9.320 ns | 9.753 ns | ? | ? | - | - | ? | +| 'ThrowIfNotContainsType - type' | .NET 10.0 | 12.265 ns | 0.1538 ns | 0.1438 ns | 12.224 ns | 12.027 ns | 12.477 ns | ? | ? | - | - | ? | +| 'ThrowIfNotContainsType - object' | .NET 10.0 | 69.293 ns | 2.8974 ns | 3.2205 ns | 68.082 ns | 65.630 ns | 76.254 ns | ? | ? | 0.0079 | 128 B | ? | +| 'ThrowIfNotContainsType - generic' | .NET 10.0 | 12.482 ns | 0.4195 ns | 0.4831 ns | 12.223 ns | 12.100 ns | 13.764 ns | ? | ? | - | - | ? | +| 'ThrowIfNotContainsType - generic message' | .NET 10.0 | 11.491 ns | 0.2186 ns | 0.2045 ns | 11.418 ns | 11.230 ns | 11.858 ns | ? | ? | - | - | ? | +| | | | | | | | | | | | | | +| 'ThrowIfContainsType - object' | .NET 9.0 | 14.352 ns | 0.2013 ns | 0.1681 ns | 14.332 ns | 14.176 ns | 14.778 ns | ? | ? | - | - | ? | +| 'ThrowIfContainsType - type' | .NET 9.0 | 14.217 ns | 0.1026 ns | 0.0959 ns | 14.211 ns | 14.078 ns | 14.393 ns | ? | ? | - | - | ? | +| 'ThrowIfContainsType - generic' | .NET 9.0 | 14.625 ns | 0.4303 ns | 0.4783 ns | 14.382 ns | 14.214 ns | 15.822 ns | ? | ? | - | - | ? | +| 'ThrowIfContainsType - generic message' | .NET 9.0 | 13.995 ns | 0.0549 ns | 0.0513 ns | 13.998 ns | 13.899 ns | 14.085 ns | ? | ? | - | - | ? | +| 'ThrowIfNotContainsType - type' | .NET 9.0 | 19.452 ns | 0.3213 ns | 0.2683 ns | 19.427 ns | 19.045 ns | 19.877 ns | ? | ? | - | - | ? | +| 'ThrowIfNotContainsType - object' | .NET 9.0 | 73.198 ns | 2.0043 ns | 1.9685 ns | 73.247 ns | 70.523 ns | 79.435 ns | ? | ? | 0.0081 | 128 B | ? | +| 'ThrowIfNotContainsType - generic' | .NET 9.0 | 18.442 ns | 0.2489 ns | 0.2079 ns | 18.410 ns | 18.260 ns | 19.085 ns | ? | ? | - | - | ? | +| 'ThrowIfNotContainsType - generic message' | .NET 9.0 | 18.877 ns | 0.0916 ns | 0.0856 ns | 18.852 ns | 18.718 ns | 19.037 ns | ? | ? | - | - | ? | diff --git a/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs index f100d8d1..867b0db3 100644 --- a/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs +++ b/tuning/Cuemon.Kernel.Benchmarks/HasDifferenceBenchmark.cs @@ -35,6 +35,7 @@ public enum DifferenceScenario /// ) across representative set-difference scenarios and lengths. /// [MemoryDiagnoser] + [WarmupCount(3)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class HasDifferenceBenchmark { diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs index f552b07c..29321b45 100644 --- a/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorCoreBenchmark.cs @@ -10,6 +10,7 @@ namespace Cuemon /// Measures the common guard, state, and comparison members of . /// [MemoryDiagnoser] + [WarmupCount(3)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class ValidatorCoreBenchmark { diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs index 76d8b96c..4c0095ce 100644 --- a/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorFormatBenchmark.cs @@ -10,6 +10,7 @@ namespace Cuemon /// treat them as compile-time constants and elide the guard. /// [MemoryDiagnoser] + [WarmupCount(3)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class ValidatorFormatBenchmark { diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs index 30829554..df80b726 100644 --- a/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorMiscBenchmark.cs @@ -10,6 +10,7 @@ namespace Cuemon /// expected so the run is not invalidated. /// [MemoryDiagnoser] + [WarmupCount(3)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class ValidatorMiscBenchmark { diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs index eca0ce62..bf9e9a73 100644 --- a/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorStringBenchmark.cs @@ -10,6 +10,7 @@ namespace Cuemon /// the guards away as compile-time constants. /// [MemoryDiagnoser] + [WarmupCount(3)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class ValidatorStringBenchmark { diff --git a/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs b/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs index fb19d105..633855dc 100644 --- a/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs +++ b/tuning/Cuemon.Kernel.Benchmarks/ValidatorTypeBenchmark.cs @@ -9,6 +9,7 @@ namespace Cuemon /// Measures the interface and type-members of . /// [MemoryDiagnoser] + [WarmupCount(3)] [GroupBenchmarksBy(BenchmarkLogicalGroupRule.ByCategory)] public class ValidatorTypeBenchmark { @@ -17,6 +18,10 @@ public class ValidatorTypeBenchmark private readonly Type[] _baseTypes = { typeof(Exception) }; private readonly Type[] _interfaceTypes = { typeof(IConvertible) }; + // Preallocated static array used by the interface-allocation attribution benchmarks + // to isolate the call-site params[] allocation from the implementation allocation. + private static readonly Type[] StaticInterfaceTypes = { typeof(IConvertible) }; + /// /// Measures the generic interface inclusion guard. /// @@ -77,6 +82,64 @@ public void ThrowIfNotContainsInterface_Type() Validator.ThrowIfNotContainsInterface(typeof(string), _interfaceTypes); } + /// + /// Attribution baseline: inclusion guard with an inline params Type[] argument. + /// The compiler emits a fresh Type[1] at the call site, so this pays the call-site + /// array allocation on top of the implementation allocation. + /// + [Benchmark(Description = "ContainsInterface - inline params[]")] + [BenchmarkCategory("Interface allocation")] + public void ContainsInterface_InlineParams() + { + Validator.ThrowIfContainsInterface(ParamName, typeof(IConvertible)); + } + + /// + /// Attribution baseline: inclusion guard with a preallocated static Type[]. + /// No call-site array is allocated, so this isolates the implementation allocation + /// (the defensive copy returned by ). + /// + [Benchmark(Description = "ContainsInterface - preallocated static[]")] + [BenchmarkCategory("Interface allocation")] + public void ContainsInterface_PreallocatedStatic() + { + Validator.ThrowIfContainsInterface(ParamName, StaticInterfaceTypes); + } + + /// + /// Attribution baseline: inclusion guard via the non-params overload + /// with a preallocated array. Confirms the non-params path allocates the same as the + /// preallocated params path. + /// + [Benchmark(Description = "ContainsInterface - non-params Type overload")] + [BenchmarkCategory("Interface allocation")] + public void ContainsInterface_NonParamsOverload() + { + Validator.ThrowIfContainsInterface(typeof(Stream), StaticInterfaceTypes); + } + + /// + /// Attribution baseline: exclusion guard with an inline params Type[] argument. + /// + [Benchmark(Description = "NotContainsInterface - inline params[]")] + [BenchmarkCategory("Interface allocation")] + public void NotContainsInterface_InlineParams() + { + Validator.ThrowIfNotContainsInterface(ParamName, typeof(IConvertible)); + } + + /// + /// Attribution baseline: exclusion guard with a preallocated static Type[]. + /// Isolates the implementation allocation; the residual scales with the number of interfaces + /// implemented by the source type (string implements many => larger array). + /// + [Benchmark(Description = "NotContainsInterface - preallocated static[]")] + [BenchmarkCategory("Interface allocation")] + public void NotContainsInterface_PreallocatedStatic() + { + Validator.ThrowIfNotContainsInterface(ParamName, StaticInterfaceTypes); + } + /// /// Measures the object type inclusion guard. /// From e50c240beb4a2851ca45f2ca9656717e0eb2f011 Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 22:31:28 +0200 Subject: [PATCH 11/15] =?UTF-8?q?=F0=9F=93=A6=20update=20package=20release?= =?UTF-8?q?=20notes=20for=20v10.5.5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Updated all per-package release notes documenting version 10.5.5 with dependency upgrades to latest compatible versions across all supported target frameworks and new Kernel module benchmarking infrastructure. --- .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../Cuemon.AspNetCore/PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.Core.App/PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.Core/PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.Data/PackageReleaseNotes.txt | 6 ++++++ .../Cuemon.Diagnostics/PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.IO/PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.Kernel/PackageReleaseNotes.txt | 17 +++++++++++++++++ .nuget/Cuemon.Net/PackageReleaseNotes.txt | 6 ++++++ .../Cuemon.Resilience/PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .../PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.Threading/PackageReleaseNotes.txt | 6 ++++++ .nuget/Cuemon.Xml/PackageReleaseNotes.txt | 6 ++++++ 43 files changed, 269 insertions(+) diff --git a/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt index 05d6f9a5..2d3eef7f 100644 --- a/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.App/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt index 92e420b3..3b7ccf02 100644 --- a/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.Authentication/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt index 75e2208a..bb4fad35 100644 --- a/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.Mvc/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt index 05d6f9a5..2d3eef7f 100644 --- a/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore.Razor.TagHelpers/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt b/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt index 193c7170..93bf3056 100644 --- a/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.AspNetCore/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt b/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt index 167989b0..66ed71ce 100644 --- a/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Core.App/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Core/PackageReleaseNotes.txt b/.nuget/Cuemon.Core/PackageReleaseNotes.txt index 6f083854..2f25ce0a 100644 --- a/.nuget/Cuemon.Core/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Core/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt b/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Data.Integrity/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt b/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt index ea99abb5..af3c38e2 100644 --- a/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Data.SqlClient/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Data/PackageReleaseNotes.txt b/.nuget/Cuemon.Data/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Data/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Data/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt b/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Diagnostics/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt index 05d6f9a5..2d3eef7f 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Authentication/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt index 6cd949d2..8e476f9c 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt index b3ddf92e..e319af2d 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.Formatters.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt index 05d6f9a5..2d3eef7f 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc.RazorPages/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt index 3158b857..cb85b732 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Mvc/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt index fce345e2..4f93f8ad 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt index 9053a7ce..17839099 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt index 3e2823f9..b6d91d66 100644 --- a/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.AspNetCore/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10 and .NET 9 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10 and .NET 9 diff --git a/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt index 63cfd86b..5111759f 100644 --- a/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Collections.Generic/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Collections.Specialized/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt index 9583a0dd..f6b5a71a 100644 --- a/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Core/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Data.Integrity/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Data/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt index 41560fd6..cb99152a 100644 --- a/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.DependencyInjection/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt index 75e0641b..39536d0a 100644 --- a/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Diagnostics/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt index f96a8820..1dbec225 100644 --- a/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Hosting/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt index 13138d45..f15b7390 100644 --- a/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.IO/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9, .NET Standard 2.1 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9, .NET Standard 2.1 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Net/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Reflection/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Runtime.Caching/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt index 7cb8ac97..902adf77 100644 --- a/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Text.Json/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Text/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt index 6e720d15..34baf790 100644 --- a/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Threading/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt index 5c1bbd9d..fed7b885 100644 --- a/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Extensions.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.IO/PackageReleaseNotes.txt b/.nuget/Cuemon.IO/PackageReleaseNotes.txt index 9d45d471..b8748c6a 100644 --- a/.nuget/Cuemon.IO/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.IO/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt b/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt index e16649c0..edd4f7d8 100644 --- a/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Kernel/PackageReleaseNotes.txt @@ -1,3 +1,20 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + +# Improvements +- OPTIMIZED Condition.IsBase64 to use System.Buffers.Text.Base64 for net9.0+ while maintaining netstandard2.0 compatibility +- OPTIMIZED Condition.IsBinaryDigits, IsHexadecimal, and IsWhiteSpace by replacing LINQ calls with direct character iteration to eliminate allocations in hot paths +- OPTIMIZED Condition.HasDifference with bitmap-based character tracking for net9.0+ for improved performance on modern runtimes +- OPTIMIZED Validator through refactored helper methods (ContainsInterfaceCore, ContainsTypeCore) to reduce method overhead and inline null validation checks +- OPTIMIZED Validator.ContainsAny with net9.0+ Span-based optimizations for case-insensitive string searching +- REFACTORED Validator error-handling deferred-evaluation patterns to compute error messages only when exceptions are thrown + +# New Features +- ADDED Cuemon.Kernel.Benchmarks project with comprehensive performance measurement suites for core validation and condition utilities: HasDifferenceBenchmark, ValidatorCoreBenchmark, ValidatorFormatBenchmark, ValidatorMiscBenchmark, ValidatorStringBenchmark, and ValidatorTypeBenchmark + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Net/PackageReleaseNotes.txt b/.nuget/Cuemon.Net/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Net/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Net/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt b/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Resilience/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt b/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt index 1547aa0f..eb5b549d 100644 --- a/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Runtime.Caching/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt b/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt index db5bd4b3..75128999 100644 --- a/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Security.Cryptography/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Threading/PackageReleaseNotes.txt b/.nuget/Cuemon.Threading/PackageReleaseNotes.txt index 85d539a5..67a190e1 100644 --- a/.nuget/Cuemon.Threading/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Threading/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 diff --git a/.nuget/Cuemon.Xml/PackageReleaseNotes.txt b/.nuget/Cuemon.Xml/PackageReleaseNotes.txt index bf397729..052da3e2 100644 --- a/.nuget/Cuemon.Xml/PackageReleaseNotes.txt +++ b/.nuget/Cuemon.Xml/PackageReleaseNotes.txt @@ -1,3 +1,9 @@ +Version: 10.5.5 +Availability: .NET 10, .NET 9 and .NET Standard 2.0 + +# ALM +- CHANGED Dependencies have been upgraded to the latest compatible versions for all supported target frameworks (TFMs) + Version: 10.5.4 Availability: .NET 10, .NET 9 and .NET Standard 2.0 From a231501bf2ce800c226f75db35acf5d137a2085e Mon Sep 17 00:00:00 2001 From: "aicia[bot]" Date: Thu, 16 Jul 2026 22:31:45 +0200 Subject: [PATCH 12/15] =?UTF-8?q?=F0=9F=92=AC=20document=20v10.5.5=20relea?= =?UTF-8?q?se=20in=20changelog?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added comprehensive changelog entry for version 10.5.5 documenting new Cuemon.Kernel.Benchmarks infrastructure, performance optimizations in Condition and Validator classes, dependency upgrades across all packages, DocFX tooling updates, and CI/CD pipeline security improvements. --- CHANGELOG.md | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8d0d988..6c10e217 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,31 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), For more details, please refer to `PackageReleaseNotes.txt` on a per assembly basis in the `.nuget` folder. +## [10.5.5] - 2026-07-16 + +This patch release provides systematic dependency updates across all supported target frameworks, alongside new benchmarking infrastructure for the Kernel module. + +> [!NOTE] +> Although primarily a service update, this release also delivers substantial performance improvements across several core validation and condition methods. Common Base64, enum, hexadecimal, string, type, and interface checks now execute faster and with significantly fewer allocations, while preserving existing behavior and public APIs. + +### Added + +- **`Cuemon.Kernel.Benchmarks`** project with dedicated performance measurement suites: `HasDifferenceBenchmark`, `ValidatorCoreBenchmark`, `ValidatorFormatBenchmark`, `ValidatorMiscBenchmark`, `ValidatorStringBenchmark`, `ValidatorTypeBenchmark`, +- Comprehensive enum parsing matrix tests in `ConditionTest` covering diverse enum types (negative values, [Flags] attributes, non-enum comparisons), +- Benchmark warmup tuning across all Kernel module performance suites for improved measurement accuracy and reduced noise in micro-benchmark results. + +### Changed + +- `Condition` class performance optimizations: `IsBase64` now uses `System.Buffers.Text.Base64` for net9.0+, `IsBinaryDigits`, `IsHexadecimal`, `IsWhiteSpace` now use direct character iteration eliminating LINQ allocations, `HasDifference` optimized with bitmap-based character tracking for net9.0+, +- `Validator` class refactored with dedicated helper methods (`ContainsInterfaceCore`, `ContainsTypeCore`) to reduce method overhead, optimized `ContainsAny` with net9.0+ Span-based string searching, restructured error-handling patterns to defer error message evaluation until exceptions are thrown, +- All package dependencies upgraded to latest compatible versions: `Codebelt.Extensions.Xunit` (11.0.9 → 11.1.1), `Codebelt.Extensions.BenchmarkDotNet.Console` (1.2.6 → 1.3.1), `Microsoft.NET.Test.Sdk` (18.5.1 → 18.8.1), Microsoft.Data.Sqlite (10.0.8 → 10.0.10, 9.0.16 → 9.0.18 for net9), Microsoft.Extensions.* packages (10.0.8 → 10.0.10, 9.0.16 → 9.0.18 for net9), `System.Text.Json` (10.0.8 → 10.0.10), `Microsoft.Data.SqlClient` (7.0.1 → 7.0.2), +- DocFX build infrastructure updated to align with latest tooling requirements, +- CI/CD pipeline permissions refined for improved security posture. + +### Fixed + +- Deploy job gating logic to explicitly depend on direct job dependencies only, ensuring deployment proceeds correctly when optional test matrices are skipped in workflow_dispatch runs. + ## [10.5.4] - 2026-06-20 This is a patch release focused on dependency maintenance and comprehensive API documentation improvements. The release significantly expands published type-level and namespace-level guidance with concrete consumer-oriented examples, establishes DocFX documentation standards, and refactors test infrastructure for improved efficiency. @@ -1798,6 +1823,7 @@ This release was primarily focused on adapting a more modern way of performing C - XmlWriterUtility class from Cuemon.Xml namespace - XmlWriterUtilityExtensions class from the Cuemon.Xml namespace +[10.5.5]: https://github.com/codebeltnet/cuemon/compare/v10.5.4...v10.5.5 [10.5.4]: https://github.com/codebeltnet/cuemon/compare/v10.5.3...v10.5.4 [10.5.3]: https://github.com/codebeltnet/cuemon/compare/v10.5.2...v10.5.3 [10.5.2]: https://github.com/codebeltnet/cuemon/compare/v10.5.1...v10.5.2 From 15db39517d302bf5165d3f66fe43d12671cacea4 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Thu, 16 Jul 2026 22:39:09 +0200 Subject: [PATCH 13/15] =?UTF-8?q?=F0=9F=94=A7=20update=20changelog=20with?= =?UTF-8?q?=20performance=20optimizations=20and=20dependency=20upgrades?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c10e217..c00e2ad8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,8 +24,7 @@ This patch release provides systematic dependency updates across all supported t - `Condition` class performance optimizations: `IsBase64` now uses `System.Buffers.Text.Base64` for net9.0+, `IsBinaryDigits`, `IsHexadecimal`, `IsWhiteSpace` now use direct character iteration eliminating LINQ allocations, `HasDifference` optimized with bitmap-based character tracking for net9.0+, - `Validator` class refactored with dedicated helper methods (`ContainsInterfaceCore`, `ContainsTypeCore`) to reduce method overhead, optimized `ContainsAny` with net9.0+ Span-based string searching, restructured error-handling patterns to defer error message evaluation until exceptions are thrown, - All package dependencies upgraded to latest compatible versions: `Codebelt.Extensions.Xunit` (11.0.9 → 11.1.1), `Codebelt.Extensions.BenchmarkDotNet.Console` (1.2.6 → 1.3.1), `Microsoft.NET.Test.Sdk` (18.5.1 → 18.8.1), Microsoft.Data.Sqlite (10.0.8 → 10.0.10, 9.0.16 → 9.0.18 for net9), Microsoft.Extensions.* packages (10.0.8 → 10.0.10, 9.0.16 → 9.0.18 for net9), `System.Text.Json` (10.0.8 → 10.0.10), `Microsoft.Data.SqlClient` (7.0.1 → 7.0.2), -- DocFX build infrastructure updated to align with latest tooling requirements, -- CI/CD pipeline permissions refined for improved security posture. +- DocFX build infrastructure updated to align with latest tooling requirements. ### Fixed From cd11b05c7d0ad74fe4b36de1b9054f25c57105be Mon Sep 17 00:00:00 2001 From: gimlichael Date: Thu, 16 Jul 2026 22:39:17 +0200 Subject: [PATCH 14/15] =?UTF-8?q?=F0=9F=94=A7=20update=20ci=20pipeline=20p?= =?UTF-8?q?ermissions=20and=20secret=20variable=20names?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/ci-pipeline.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/ci-pipeline.yml b/.github/workflows/ci-pipeline.yml index ac24f59a..bcb2eb18 100644 --- a/.github/workflows/ci-pipeline.yml +++ b/.github/workflows/ci-pipeline.yml @@ -391,9 +391,7 @@ jobs: environment: Production configuration: ${{ inputs.configuration == '' && 'Release' || inputs.configuration }} permissions: - actions: read contents: read packages: write - id-token: write secrets: - NUGET_USER: ${{ secrets.NUGET_USER }} + NUGET_TOKEN: ${{ secrets.NUGET_TOKEN }} From ea6aea219288cd135b167c4a33152004d86ffaf3 Mon Sep 17 00:00:00 2001 From: gimlichael Date: Thu, 16 Jul 2026 23:26:53 +0200 Subject: [PATCH 15/15] =?UTF-8?q?=E2=9C=A8=20add=20tests=20for=20hasDiffer?= =?UTF-8?q?ence=20with=20non-ASCII=20and=20mixed=20characters?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/Cuemon.Kernel.Tests/ConditionTest.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Cuemon.Kernel.Tests/ConditionTest.cs b/test/Cuemon.Kernel.Tests/ConditionTest.cs index 20e700cc..33c7dd22 100644 --- a/test/Cuemon.Kernel.Tests/ConditionTest.cs +++ b/test/Cuemon.Kernel.Tests/ConditionTest.cs @@ -538,9 +538,15 @@ public void HasDifference_ShouldHandleNonAsciiCharacters() Assert.False(Condition.HasDifference("ÆØÅ", "ÅØÆ", out var noDifference)); Assert.Equal(string.Empty, noDifference); + Assert.True(Condition.HasDifference("abc", "abc本本", out var asciiFirstDifference)); + Assert.Equal("本", asciiFirstDifference); + Assert.True(Condition.HasDifference("ÆØ", "ÆØÅÅ", out var difference)); Assert.Equal("Å", difference); + Assert.True(Condition.HasDifference("AĀ", "ĀA本本", out var mixedFirstDifference)); + Assert.Equal("本", mixedFirstDifference); + // characters outside the Latin-1 range (>= U+0100) Assert.False(Condition.HasDifference("Ā日本", "本日Ā", out var noDifferenceBmp)); Assert.Equal(string.Empty, noDifferenceBmp);