我的小程序正在检查脚本网站使用的类型,它使用超过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
在另一个班级
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
};
}
Match(url)函数在ForeachAsyncLoop中,程序检查大约4000个链接/分钟。当我禁用所有正则表达式时,它使用高达20%的cpu,我可以提高正则表达式的性能吗?强调文本
答案 0 :(得分:5)
你可能无法使用正则表达式加快速度。但是,使用不同的算法可能会做得更好。
Aho-Corasick string matching algorithm旨在完成你正在做的事情:在大量文本中寻找一组固定的字符串。
标准算法不支持正则表达式,但您的正则表达式是逐字字符串。也就是说,您正在寻找this|that|something else|something more
。这与查找四个不同的字符串相同。
几年前我发布了Aho-Corasick algorithm in C#的实现。通过对您的工作方式进行一些修改,它应该可以正常工作。
首先构建您要查找的字符串字典以及相应的网站:
Dictionary<string, string> StringsToSites = new Dictionary<string, string>();
然后,添加字符串。例如,对于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.
请注意,对于非逐字字符串的内容存在问题。实现没有办法匹配“?q = node / [0-9] + /”。我们能做的最好的事情是添加字符串“?q = node /".
然后,创建一个匹配器并填充它:
AhoCorasickStringSearcher matcher = new AhoCorasickStringSearcher();
foreach (var key in StringsToSites.Keys)
{
matcher.AddItem(key);
}
matcher.CreateFailureFunction();
然后,对于您看到的每个链接,请致电matcher.Search
:
var Matches = matcher.Search(link);
这将为您提供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);
}
}
我希望这至少是你的正则表达式解决方案的10倍,可能快100倍。
答案 1 :(得分:1)
你正在做的事情是:
试图完成1&amp; 2,你可以将所有正则表达式组合成一个正则表达式。 我不认为这会在组合它们时产生性能损失。甚至可能更有效。
值得探索,因为无论如何这可能是你代码中的一个慢点。
所以,相当于你正在做的是:
Regex rxAll = new Regex(
@"
(?:
^ [\S\s]*
(?<Drupal1>
/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/
)
|
^ [\S\s]*
(?<XE1>
XpressEngine
| content=""zeroboardXE
| content=""xe_board""
| var\ zbxe_session_name
| /xe\.css\?2
| /xeicon/favicon\.ico""
| \#xe-editor-container-1
| xpress_xeditor
)
)
", RegexOptions.IgnorePatternWhitespace);
string html =
@"
<a class=""x-fn"" href=""javascript:void(0);"">
<a class='x-fn' href = ""javascript:void(0); "">
<a href='javascript:void(0);' class=x-fn >
<a class=""x-fn"" href=javascript:void(0); >
<a 'hello' href=javascript:void(0); world class=x-fn content=""xe_board"">
";
Match matches = rxAll.Match( html );
if (matches.Success)
{
if (matches.Groups["Drupal1"].Success)
{
Console.WriteLine("Matched Drupal1 -> {0}", matches.Groups["Drupal1"].Value);
return;
}
if (matches.Groups["XE1"].Success)
{
Console.WriteLine("Matched XE1 -> {0}", matches.Groups["XE1"].Value);
return;
}
}
return;
编辑:BTW,我在你的正则表达式上使用了RegexFormat(.com)程序。这些Verbatim正则表达式是 只需按几下按钮即可完成。因此,您可以使用工具为您完成所有工作。