Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 22 additions & 21 deletions src/System.Management.Automation/engine/lang/parserutils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@
// Licensed under the MIT License.
Comment thread
SteveL-MSFT marked this conversation as resolved.

using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Management.Automation.Internal;
using System.Management.Automation.Internal.Host;
using System.Management.Automation.Language;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;

using Dbg = System.Management.Automation.Diagnostics;
Expand Down Expand Up @@ -1347,35 +1346,37 @@ internal static object CompareOperators(ExecutionContext context, IScriptExtent
}
Comment thread
iSazonov marked this conversation as resolved.
Outdated
Comment thread
iSazonov marked this conversation as resolved.
Outdated
Comment thread
iSazonov marked this conversation as resolved.
Outdated

/// <summary>
/// Cache regular expressions...
/// Cache regular expressions.
/// </summary>
/// <param name="patternString">The string to find the pattern for.</param>
/// <param name="options">The options used to create the regex...</param>
/// <returns>A case-insensitive Regex...</returns>
/// <param name="options">The options used to create the regex.</param>
/// <returns>New or cached Regex.</returns>
internal static Regex NewRegex(string patternString, RegexOptions options)
{
if (options != RegexOptions.IgnoreCase)
return new Regex(patternString, options);

lock (s_regexCache)
var subordinateRegexCache = s_regexCache.GetOrAdd(options, s_subordinateRegexCacheCreationDelegate);
if (subordinateRegexCache.TryGetValue(patternString, out Regex result))
{
Regex result;
if (s_regexCache.TryGetValue(patternString, out result))
{
return result;
}
else
return result;
}
else
{
if (subordinateRegexCache.Count > MaxRegexCache)
{
if (s_regexCache.Count > MaxRegexCache)
s_regexCache.Clear();
Regex re = new Regex(patternString, RegexOptions.IgnoreCase);
s_regexCache.Add(patternString, re);
return re;
// TODO: it would be useful to get a notice (in telemetry?) if the cache is full.
subordinateRegexCache.Clear();
}

var regex = new Regex(patternString, options);
return subordinateRegexCache.GetOrAdd(patternString, regex);
}
}

private static Dictionary<string, Regex> s_regexCache = new Dictionary<string, Regex>();
private static readonly ConcurrentDictionary<RegexOptions, ConcurrentDictionary<string, Regex>> s_regexCache =
new ConcurrentDictionary<RegexOptions, ConcurrentDictionary<string, Regex>>();

private static readonly Func<RegexOptions, ConcurrentDictionary<string, Regex>> s_subordinateRegexCacheCreationDelegate =
key => new ConcurrentDictionary<string, Regex>(StringComparer.Ordinal);

private const int MaxRegexCache = 1000;

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/System.Management.Automation/engine/regex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -909,7 +909,7 @@ public static Regex Parse(WildcardPattern wildcardPattern)
WildcardPatternParser.Parse(wildcardPattern, parser);
try
{
return new Regex(parser._regexPattern.ToString(), parser._regexOptions);
return ParserOps.NewRegex(parser._regexPattern.ToString(), parser._regexOptions);
}
catch (ArgumentException)
{
Expand Down Expand Up @@ -1258,7 +1258,7 @@ protected override void AppendCharacterRangeToBracketExpression(
protected override void EndBracketExpression()
{
_bracketExpressionBuilder.Append(']');
Regex regex = new Regex(_bracketExpressionBuilder.ToString(), _regexOptions);
Regex regex = ParserOps.NewRegex(_bracketExpressionBuilder.ToString(), _regexOptions);
_patternElements.Add(new BracketExpressionElement(regex));
}
}
Expand Down