c#regex高CPU使用率

eka*_*pek 6 c# regex

我的小程序正在检查脚本网站使用的是什么类型,它使用超过80%的cpu i7处理器.我不知道这是正常的吗?

码:

public static class EnginesMatcher
{

    public static readonly Regex Drupal1 =
        new Regex(
            @"/misc/drupal\.js|Drupal\.settings|href=""http://drupal\.org""|\?q=node/[0-9]+|/\?q=user/register|/\?q=user/password|/user/register\?destination|<li class=""collapsed""><a href=""/node/add"">|/dpl3/files/|/modules/node/",
            RegexOptions.Compiled);

    public static readonly Regex XE1 =
        new Regex(
        @"XpressEngine|content=""zeroboardXE|content=""xe_board""|var zbxe_session_name|/xe\.css\?2|/xeicon/favicon\.ico""|#xe-editor-container-1|xpress_xeditor",
            RegexOptions.Compiled);

    //and 60 more such regex
Run Code Online (Sandbox Code Playgroud)

在另一堂课

  public async Task<Result> Match(string url)
        {

            if (!await Open(url).ConfigureAwait(false)) return ResultKey;


            if (EnginesMatcher.Drupal1.IsMatch(html))
            {
                return new Result()
                {
                    Key = AResultKey.Success,
                    LogFile = "Drupal.txt",
                    Message = "Drupal",
                    Url = url
                };
            }
            if (EnginesMatcher.XE1.IsMatch(html))
            {
                return new Result()
                {
                    Key = AResultKey.Success,
                    LogFile = "Drupal.txt",
                    Message = "Drupal",
                    Url = url
                };
            }
Run Code Online (Sandbox Code Playgroud)

Match(url)函数在ForeachAsyncLoop中,程序检查大约4000个链接/分钟.当我禁用所有正则表达式时,它使用高达20%的CPU,我可以提高正则表达式的性能吗?强调文字

Jim*_*hel 5

你可能无法使用正则表达式加快速度.但是,通过使用不同的算法,您可以做得更好.

阿霍Corasick字符串匹配算法的目的是做你正在做什么:寻找一个大段文字的一组固定字符串.

标准算法不支持正则表达式,但您的正则表达式是逐字字符串.也就是说,你正在寻找this|that|something else|something more.这与寻找四种不同的字符串相同.

几年前我在C#中发布了Aho-Corasick算法的实现.通过对您的工作方式进行一些修改,它应该可以正常工作.

首先构建您要查找的字符串字典以及相应的网站:

Dictionary<string, string> StringsToSites = new Dictionary<string, string>();
Run Code Online (Sandbox Code Playgroud)

然后,添加字符串.例如,对于Drupal,您需要添加:

StringsToSites.Add("/misc/drupal\.js", "Drupal");
StringsToSites.Add("Drupal.settings", "Drupal");
StringsToSites.Add(@"href=""http://drupal\.org"", "Drupal");
// problem with this one ...   |\?q=node/[0-9]+
StringsToSites.Add("?q=user/register", "Drupal");
// etc., etc.
Run Code Online (Sandbox Code Playgroud)

请注意,对于非逐字字符串的内容存在问题.实现没有办法匹配"?q = node/[0-9] + /".我们能做的最好的事情是添加字符串"?q = node /".

然后,创建一个匹配器并填充它:

AhoCorasickStringSearcher matcher = new AhoCorasickStringSearcher();
foreach (var key in StringsToSites.Keys)
{
    matcher.AddItem(key);
}
matcher.CreateFailureFunction();
Run Code Online (Sandbox Code Playgroud)

然后,对于您看到的每个链接,请致电matcher.Search:

var Matches = matcher.Search(link);    
Run Code Online (Sandbox Code Playgroud)

这将为您提供一组StringMatch对象.您可以Text在字典中查找它以匹配哪个站点.例如:

foreach (var m in Matches)
{
    string site;
    if (StringsToSites.TryGetValue(m.Text, out site))
    {
        Console.WriteLine("Text '{0}' matches site '{1}'.", m.Text, site);
    }
}
Run Code Online (Sandbox Code Playgroud)

我希望这至少是你的正则表达式解决方案的10倍,可能快100倍.