From fbbbc45c24c84af5941c9504d496083582efee52 Mon Sep 17 00:00:00 2001 From: Henrik Date: Sun, 28 Sep 2025 23:40:50 +0200 Subject: [PATCH] Micro-optimization: Move compilation of some Regex generation to compile time instead of runtime, make some static ones compiled (#20287) Move compilation of some Regex generation to compile time instead of runtime, make some static ones compiled --- src/Umbraco.Core/IO/ShadowFileSystem.cs | 30 ++++++++++++++----- .../Templates/HtmlLocalLinkParser.cs | 6 ++-- .../Persistence/NPocoDatabaseExtensions.cs | 8 +++-- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Core/IO/ShadowFileSystem.cs b/src/Umbraco.Core/IO/ShadowFileSystem.cs index ef35006ef5..31e884454f 100644 --- a/src/Umbraco.Core/IO/ShadowFileSystem.cs +++ b/src/Umbraco.Core/IO/ShadowFileSystem.cs @@ -2,7 +2,7 @@ using System.Text.RegularExpressions; namespace Umbraco.Cms.Core.IO; -internal sealed class ShadowFileSystem : IFileSystem +internal sealed partial class ShadowFileSystem : IFileSystem { private readonly IFileSystem _sfs; @@ -392,14 +392,28 @@ internal sealed class ShadowFileSystem : IFileSystem } // copied from System.Web.Util.Wildcard internal - internal sealed class WildcardExpression + internal sealed partial class WildcardExpression { - private static readonly Regex MetaRegex = new("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]"); - private static readonly Regex QuestRegex = new("\\?"); - private static readonly Regex StarRegex = new("\\*"); - private static readonly Regex CommaRegex = new(","); - private static readonly Regex SlashRegex = new("(?=/)"); - private static readonly Regex BackslashRegex = new("(?=[\\\\:])"); + private static readonly Regex MetaRegex = GetMetaRegex(); + + [GeneratedRegex("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]")] + private static partial Regex GetMetaRegex(); + + private static readonly Regex QuestRegex = GetQuestRegex(); + + [GeneratedRegex("\\?")] + private static partial Regex GetQuestRegex(); + + private static readonly Regex StarRegex = GetStarRegex(); + + [GeneratedRegex("\\*")] + private static partial Regex GetStarRegex(); + + private static readonly Regex CommaRegex = GetCommaRegex(); + + [GeneratedRegex(",")] + private static partial Regex GetCommaRegex(); + private readonly bool _caseInsensitive; private readonly string _pattern; private Regex? _regex; diff --git a/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs b/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs index 73aec2e74d..468d9b462a 100644 --- a/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs +++ b/src/Umbraco.Core/Templates/HtmlLocalLinkParser.cs @@ -15,15 +15,15 @@ public sealed class HtmlLocalLinkParser // other page internal static readonly Regex LocalLinkTagPattern = new( @"\/?{localLink:(?[a-fA-F0-9-]+)})[^>]*?>", - RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline); + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Singleline | RegexOptions.Compiled); internal static readonly Regex TypePattern = new( """type=['"](?(?:media|document))['"]""", - RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); internal static readonly Regex LocalLinkPattern = new( @"href=['""](?\/?(?:\{|\%7B)localLink:(?[a-zA-Z0-9-://]+)(?:\}|\%7D))", - RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace); + RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Compiled); private readonly IPublishedUrlProvider _publishedUrlProvider; diff --git a/src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs b/src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs index bebf59cbe7..7ad54ba16e 100644 --- a/src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs +++ b/src/Umbraco.Infrastructure/Persistence/NPocoDatabaseExtensions.cs @@ -225,16 +225,18 @@ public static partial class NPocoDatabaseExtensions /// public static string EscapeAtSymbols(string value) { - if (value.Contains("@") == false) + if (value.Contains('@') == false) { return value; } // this fancy regex will only match a single @ not a double, etc... - var regex = new Regex("(? /// Returns the underlying connection as a typed connection - this is used to unwrap the profiled mini profiler stuff ///