-
Notifications
You must be signed in to change notification settings - Fork 239
Improve S5332 performance: Reuse compiled regex #8181
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve S5332 performance: Reuse compiled regex #8181
Conversation
andrei-epure-sonarsource
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Please address the SC failed QG before merging.
| { | ||
| } | ||
|
|
||
| static ClearTextProtocolsAreSensitive() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
regarding the https://rules.sonarsource.com/csharp/RSPEC-3963/
I've marked it as FP after a discussion with @martin-strecker-sonarsource :
It is an FP because you can not move the logic to field initializers as suggested. It requires SE to figure this out because you have to look at the code flow (one variable is used to initialize more than one field).
@denis-troller open question whether we want to turn this rule into a Symbolic Execution rule, to avoid False Positives and only raise if the fix is doable
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, couldn't you replace with
private static readonly Lazy<string> ValidServerPattern = new Lazy<string>(() =>
{
const string allSubdomainsPattern = @"([^/?#]+\.)?";
var domainsList = LocalhostAddresses
.Concat(CommonlyUsedXmlDomains)
.Select(Regex.Escape)
.Concat(CommonlyUsedExampleDomains.Select(x => allSubdomainsPattern + Regex.Escape(x)));
return domainsList.JoinStr("|");
});
private static readonly Regex HttpRegex = CompileRegex(@$"^http:\/\/(?!{ValidServerPattern.Value}).");
private static readonly Regex FtpRegex = CompileRegex(@$"^ftp:\/\/.*@(?!{ValidServerPattern.Value})");
private static readonly Regex TelnetRegex = CompileRegex(@$"^telnet:\/\/.*@(?!{ValidServerPattern.Value})") ;
private static readonly Regex TelnetRegexForIdentifier = CompileRegex(@"Telnet(?![a-z])", false);
private static readonly Regex ValidServerRegex = CompileRegex($"^({ValidServerPattern.Value})$");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would work (even without the Lazy). I explicitly did not do it, as re-ordering the members would break the logic at runtime. Reordering in the static constructor breaks at compile time.
See also this comment for the same problem but for object initializers:
All that said, it really shouldn't matter. If you have a class where the order of assignments to two or more properties affects the final outcome, you've got a pretty hazardous class on your hands. Such design ought to be avoided at all costs, as it is way too easy to break in any case, even when the compiler rules for object initialization are reasonably clear.
https://stackoverflow.com/a/47959273
Or this one by John Skeet:
I would also be very wary of actually writing code which depends on this..
| { | ||
| } | ||
|
|
||
| static ClearTextProtocolsAreSensitive() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, couldn't you replace with
private static readonly Lazy<string> ValidServerPattern = new Lazy<string>(() =>
{
const string allSubdomainsPattern = @"([^/?#]+\.)?";
var domainsList = LocalhostAddresses
.Concat(CommonlyUsedXmlDomains)
.Select(Regex.Escape)
.Concat(CommonlyUsedExampleDomains.Select(x => allSubdomainsPattern + Regex.Escape(x)));
return domainsList.JoinStr("|");
});
private static readonly Regex HttpRegex = CompileRegex(@$"^http:\/\/(?!{ValidServerPattern.Value}).");
private static readonly Regex FtpRegex = CompileRegex(@$"^ftp:\/\/.*@(?!{ValidServerPattern.Value})");
private static readonly Regex TelnetRegex = CompileRegex(@$"^telnet:\/\/.*@(?!{ValidServerPattern.Value})") ;
private static readonly Regex TelnetRegexForIdentifier = CompileRegex(@"Telnet(?![a-z])", false);
private static readonly Regex ValidServerRegex = CompileRegex($"^({ValidServerPattern.Value})$");
bb8bee5 to
96d98fa
Compare
|
Kudos, SonarCloud Quality Gate passed! |
|
Kudos, SonarCloud Quality Gate passed! |
andrei-epure-sonarsource
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM








The 5 compiled regex used in ClearTextProtocolsAreSensitive are not cached between instances and are adding a significant JIT compilation overhead. This PR fixes this:
Time spend on compiling
akka.net project
Before:

After:

Overall
Before: 18th most expensive operation with 14,5 seconds

After: 55 ms
