猿问

使用 IsMatch 时的 REGEX 性能问题

我有以下用于执行重定向的正则表达式


string requestedPath = HttpUtility.UrlDecode(this.StripLanguage(currentContext.InputUrl.AbsolutePath));

string requestedPathAndQuery = HttpUtility.UrlDecode(currentContext.InputUrl.PathAndQuery);

string requestedRawUrl = HttpUtility.UrlDecode(currentContext.InputUrl.PathAndQuery);

string requestedUrl =

    HttpUtility.UrlDecode(

        string.Concat(

            currentContext.InputUrl.Scheme,

            "://",

            currentContext.InputUrl.Host,

            requestedRawUrl));


string requestedRawUrlDomainAppended = HttpUtility.UrlDecode(currentContext.InputUrl.AbsoluteUri);

string requestedPathWithCulture = HttpUtility.UrlDecode(currentContext.InputUrl.AbsolutePath);


                    var finalRequestedURL = string.Empty;

finalRequestedURL = Regex.IsMatch(requestedPathAndQuery,matchPattern.Trim(),RegexOptions.IgnoreCase)

                    ? requestedPathAndQuery

                    : Regex.IsMatch(requestedPath,matchPattern.Trim(),RegexOptions.IgnoreCase)

                        ? requestedPath

                        : Regex.IsMatch(requestedPathWithCulture,matchPattern.Trim(),RegexOptions.IgnoreCase)

                            ? requestedPathWithCulture

                            : Regex.IsMatch(requestedRawUrl,matchPattern.Trim(),RegexOptions.IgnoreCase)

                                ? requestedRawUrl

                                : Regex.IsMatch(requestedUrl,matchPattern.Trim(),RegexOptions.IgnoreCase)

                                    ? requestedRawUrlDomainAppended

                                    : string.Empty;

matchPattern变量是 URL 。示例:(.*)/articles/my-article(.*)应重定向到http://www.google.com


正则表达式工作正常,但是当涉及到大量请求时,我们的 CPU 会达到 100%。


有什么解决方案可以优化上述内容吗?


慕尼黑5688855
浏览 236回答 2
2回答

梵蒂冈之花

我会尝试创建一个实际Regex变量并重用它。这应该有助于加快速度。我也可能会建议将三元业务更改为常规的 if/else if/else 语句。我认为它会更具可读性(只是个人意见)。string requestedPath = HttpUtility.UrlDecode(this.StripLanguage(currentContext.InputUrl.AbsolutePath));string requestedPathAndQuery = HttpUtility.UrlDecode(currentContext.InputUrl.PathAndQuery);string requestedRawUrl = HttpUtility.UrlDecode(currentContext.InputUrl.PathAndQuery);string requestedUrl =    HttpUtility.UrlDecode(        string.Concat(            currentContext.InputUrl.Scheme,            "://",            currentContext.InputUrl.Host,            requestedRawUrl));string requestedRawUrlDomainAppended = HttpUtility.UrlDecode(currentContext.InputUrl.AbsoluteUri);string requestedPathWithCulture = HttpUtility.UrlDecode(currentContext.InputUrl.AbsolutePath);var regex = new Regex(matchPattern.Trim(), RegexOptions.IgnoreCase);var finalRequestedURL = regex.IsMatch(requestedPathAndQuery)                    ? requestedPathAndQuery                    : regex.IsMatch(requestedPath)                        ? requestedPath                        : regex.IsMatch(requestedPathWithCulture)                            ? requestedPathWithCulture                            : regex.IsMatch(requestedRawUrl)                                ? requestedRawUrl                                : regex.IsMatch(requestedUrl)                                    ? requestedRawUrlDomainAppended                                    : string.Empty;编辑正如我在上面的评论中指出的那样,有两个相同的字符串,如果您删除其中一个,可以节省比较。string requestedPath = HttpUtility.UrlDecode(this.StripLanguage(currentContext.InputUrl.AbsolutePath));string requestedPathAndQuery = HttpUtility.UrlDecode(currentContext.InputUrl.PathAndQuery);// This string is identical to requestPathAndQuery, so I am removing it// string requestedRawUrl = HttpUtility.UrlDecode(currentContext.InputUrl.PathAndQuery);string requestedUrl =    HttpUtility.UrlDecode(        string.Concat(            currentContext.InputUrl.Scheme,            "://",            currentContext.InputUrl.Host,            requestedRawUrl));string requestedRawUrlDomainAppended = HttpUtility.UrlDecode(currentContext.InputUrl.AbsoluteUri);string requestedPathWithCulture = HttpUtility.UrlDecode(currentContext.InputUrl.AbsolutePath);var regex = new Regex(matchPattern.Trim(), RegexOptions.IgnoreCase);var finalRequestedURL = string.Empty;// You could even add in brackets here to aid readability but this// helps remove the indententation/nesting that makes the code harder// to read and followif (regex.IsMatch(requestedPathAndQuery)) finalRequestURL = requestedPathAndQuery;else if(regex.IsMatch(requestedPath)) finalRequestURL = requestedPath;else if (regex.IsMatch(requestedPathWithCulture)) finalRequestURL = requestedPathWithCulture;else if (regex.IsMatch(requestedUrl)) finalRequestURL = requestedRawUrlDomainAppended;

森林海

正如我在评论中所说,如果您预计只有有限数量的不同模式可以在您的应用程序的生命周期中重用,您可以创建一个静态Dictionary(我认为最好使用并发模式)并缓存此正则表达式并重用它们。编辑示例代码:public class MyHandler{&nbsp; &nbsp; private static ConcurrentDictionary<string, Regex> dict = new ConcurrentDictionary<string, Regex>();&nbsp; &nbsp; public void Handle(string urlPattern)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; urlPattern = urlPattern.Trim();&nbsp; &nbsp; &nbsp; &nbsp; var regex = dict.GetOrAdd(urlPattern, s => new Regex(urlPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase));&nbsp; &nbsp; &nbsp; &nbsp; // use regex&nbsp; &nbsp; }}还要测试RegexOptions.Compiled选项是否适合您,因为它实际上会使事情变慢
随时随地看视频慕课网APP
我要回答