Thanks to visit codestin.com
Credit goes to github.com

Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Fix for Regex performance issue when compiled Regex is used with Rege…
……xOptions.IgnoreCase or RegexOptions.CultureInvariant.

This saves over 40% in these cases.
  • Loading branch information
Alois-xx committed Oct 18, 2018
commit 62d7b7c78973ecdfc8fcc20929b7954c160cca5b
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ internal abstract class RegexCompiler
private LocalBuilder _tempV;
private LocalBuilder _temp2V;
private LocalBuilder _temp3V;
private LocalBuilder _cultureV; // current culture is cached in local variable to prevent many thread local storage accesses for CultureInfo.CurrentCulture

protected RegexCode _code; // the RegexCode object (used for debugging only)
protected int[] _codes; // the RegexCodes being translated
Expand Down Expand Up @@ -961,14 +962,20 @@ private void Advance()
_ilg.Emit(OpCodes.Br, AdvanceLabel());
}

private void CallToLower()
private void InitLocalCultureInfo()
{
if ((_options & RegexOptions.CultureInvariant) != 0)
Call(s_getInvariantCulture);
else
Call(s_getCurrentCulture);

Call(s_chartolowerM);
Stloc(_cultureV);
}

private void CallToLower()
{
Ldloc(_cultureV);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the lifetime of this? e.g. does this cache end up spanning multiple regex calls and user code such that user code could change the current culture and end up with different behavior than before?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_cultureV is a local variable. The lifetime of the cache is therefore method local in FindFirstChar and Go methods of the compiled regular expression.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I see. Thanks.

Call(s_chartolowerM);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ViktorHofer, am I misremembering, or did you do some ToLower-related optimizations/changes when you were cleaning up the regex code recently? If yes, should we instead just port the appropriate changes to the compiled version? If no, is there a similar optimization to be done on the interpreted side of things?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, but only minor allocation optimizations. I wouldn't do that as part of this PR but revisit the compiled code paths later to make sure that we don't diverge and bring optimizations over.

}

/*
Expand Down Expand Up @@ -1089,6 +1096,9 @@ protected void GenerateFindFirstChar()
_textV = DeclareString();
_tempV = DeclareInt();
_temp2V = DeclareInt();
_cultureV = DeclareCultureInfo();

InitLocalCultureInfo();

if (0 != (_anchors & (RegexFCD.Beginning | RegexFCD.Start | RegexFCD.EndZ | RegexFCD.End)))
{
Expand Down Expand Up @@ -1552,6 +1562,14 @@ private LocalBuilder DeclareInt()
return _ilg.DeclareLocal(typeof(int));
}

/*
* Declares a local CultureInfo
*/
private LocalBuilder DeclareCultureInfo()
{
return _ilg.DeclareLocal(typeof(CultureInfo));
}

/*
* Declares a local int array
*/
Expand Down Expand Up @@ -1587,6 +1605,7 @@ protected void GenerateGo()
_textbegV = DeclareInt();
_textendV = DeclareInt();
_textstartV = DeclareInt();
_cultureV = DeclareCultureInfo();

// clear some tables

Expand All @@ -1600,6 +1619,9 @@ protected void GenerateGo()

// emit the code!

// cache CultureInfo in local variable which saves excessive thread local storage accesses
InitLocalCultureInfo();

GenerateForwardSection();
GenerateMiddleSection();
GenerateBacktrackSection();
Expand Down