【发布时间】:2011-08-25 16:16:25
【问题描述】:
我遇到了这篇文章:
Performance: Compiled vs. Interpreted Regular Expressions,我修改了示例代码以编译 1000 个正则表达式,然后每个运行 500 次以利用预编译,但即使在这种情况下,解释的正则表达式运行速度也快 4 倍!
这意味着 很大的不同是由于JIT,在解决JIT后编译的正则表达式在下面的代码中仍然执行有点慢对我来说没有意义,但@Jim in the answers provided a much cleaner version which works as expected。RegexOptions.Compiled选项完全没用,实际上更糟糕的是,它更慢!
谁能解释为什么会这样?
代码,取自并修改自博文:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
namespace RegExTester
{
class Program
{
static void Main(string[] args)
{
DateTime startTime = DateTime.Now;
for (int i = 0; i < 1000; i++)
{
CheckForMatches("some random text with email address, address@domain200.com" + i.ToString());
}
double msTaken = DateTime.Now.Subtract(startTime).TotalMilliseconds;
Console.WriteLine("Full Run: " + msTaken);
startTime = DateTime.Now;
for (int i = 0; i < 1000; i++)
{
CheckForMatches("some random text with email address, address@domain200.com" + i.ToString());
}
msTaken = DateTime.Now.Subtract(startTime).TotalMilliseconds;
Console.WriteLine("Full Run: " + msTaken);
Console.ReadLine();
}
private static List<Regex> _expressions;
private static object _SyncRoot = new object();
private static List<Regex> GetExpressions()
{
if (_expressions != null)
return _expressions;
lock (_SyncRoot)
{
if (_expressions == null)
{
DateTime startTime = DateTime.Now;
List<Regex> tempExpressions = new List<Regex>();
string regExPattern =
@"^[a-zA-Z0-9]+[a-zA-Z0-9._%-]*@{0}$";
for (int i = 0; i < 2000; i++)
{
tempExpressions.Add(new Regex(
string.Format(regExPattern,
Regex.Escape("domain" + i.ToString() + "." +
(i % 3 == 0 ? ".com" : ".net"))),
RegexOptions.IgnoreCase));// | RegexOptions.Compiled
}
_expressions = new List<Regex>(tempExpressions);
DateTime endTime = DateTime.Now;
double msTaken = endTime.Subtract(startTime).TotalMilliseconds;
Console.WriteLine("Init:" + msTaken);
}
}
return _expressions;
}
static List<Regex> expressions = GetExpressions();
private static void CheckForMatches(string text)
{
DateTime startTime = DateTime.Now;
foreach (Regex e in expressions)
{
bool isMatch = e.IsMatch(text);
}
DateTime endTime = DateTime.Now;
//double msTaken = endTime.Subtract(startTime).TotalMilliseconds;
//Console.WriteLine("Run: " + msTaken);
}
}
}
【问题讨论】:
-
StopWatch应该用于基准测试,而不是DateTime。 -
@Domenic 同意,我使用了 blogpost 中的代码,但不应以有用的方式影响此测试的结果
-
最大的问题是编译的Regex第一次执行时,必须进行JIT编译。 JIT 编译比实际查找匹配花费的时间更多!如果你在初始化
startTime之前运行一次CheckForMatches,你会发现时间更接近了。 -
@Gabe 好点 Gabe,我更新了代码,基本上运行了两次,我采取了第二次执行时间。我认为这将解决 JIT 问题。虽然它仍然较慢,但这次要接近得多。
标签: .net regex performance