Ben*_*iel 43 c# regex optimization
在C#中你应该有如下代码:
public static string importantRegex = "magic!";
public void F1(){
//code
if(Regex.IsMatch(importantRegex)){
//codez in here.
}
//more code
}
public void main(){
F1();
/*
some stuff happens......
*/
F1();
}
Run Code Online (Sandbox Code Playgroud)
或者你应该坚持包含重要模式的正则表达式的实例?使用Regex.IsMatch的成本是多少?我想在每个正则表达式中都会创建一个NFA.根据我的理解,这个NFA的创作并非无足轻重.
P D*_*ddy 49
与我典型的自我中心有很大的不同,我有点想要回避这个问题.
我在下面保留的原始答案是基于对.NET框架1.1版的检查.这是非常可耻的,因为.NET 2.0在我的回答时已经出了三年多了,它包含了对Regex类的更改,这些更改显着影响了静态方法和实例方法之间的差异.
在.NET 2.0(和4.0)中,静态IsMatch函数定义如下:
public static bool IsMatch(string input, string pattern){
return new Regex(pattern, RegexOptions.None, true).IsMatch(input);
}
Run Code Online (Sandbox Code Playgroud)
这里的显着差异是true第三个论点.这对应于名为"useCache"的参数.如果是这样,则在第二次和后续使用时从缓存中检索解析的树.
这种缓存会占用静态和实例方法之间的大多数但不是全部的性能差异.在我的测试中,静态IsMatch方法仍然比实例方法慢约20%,但是当在一组10,000个输入字符串上运行100次时(总共100万次操作),这只增加了大约半秒.
在某些情况下,这20%的减速仍然很重要.如果你发现自己正在重复数亿个字符串,你可能希望尽一切可能使它更有效率.但我敢打赌99%的时间,你使用特定的正则表达不会超过几次,并且你输入静态方法的额外毫秒甚至不会引人注意.
关于devgeezer的道具,几乎在一年前就指出了这一点,尽管似乎没有人注意到.
我的老答案如下:
静态IsMatch函数定义如下:
public static bool IsMatch(string input, string pattern){
return new Regex(pattern).IsMatch(input);
}
Run Code Online (Sandbox Code Playgroud)
而且,是的,Regex对象的初始化并非易事.您应该使用静态IsMatch(或任何其他静态Regex函数)作为仅使用一次的模式的快捷方式.如果您将重用该模式,那么重用一个Regex对象也是值得的.
至于你是否应该RegexOptions.Compiled像Jon Skeet所说的那样指明这是另一个故事.答案是:它取决于.对于简单模式或仅使用少数几次的模式,使用非编译实例可能会更快.在决定之前你一定要做好准备.编译正则表达式对象的成本确实非常大,可能不值得.
举个例子,如下:
const int count = 10000;
string pattern = "^[a-z]+[0-9]+$";
string input = "abc123";
Stopwatch sw = Stopwatch.StartNew();
for(int i = 0; i < count; i++)
Regex.IsMatch(input, pattern);
Console.WriteLine("static took {0} seconds.", sw.Elapsed.TotalSeconds);
sw.Reset();
sw.Start();
Regex rx = new Regex(pattern);
for(int i = 0; i < count; i++)
rx.IsMatch(input);
Console.WriteLine("instance took {0} seconds.", sw.Elapsed.TotalSeconds);
sw.Reset();
sw.Start();
rx = new Regex(pattern, RegexOptions.Compiled);
for(int i = 0; i < count; i++)
rx.IsMatch(input);
Console.WriteLine("compiled took {0} seconds.", sw.Elapsed.TotalSeconds);
Run Code Online (Sandbox Code Playgroud)
在count = 10000,作为列出的,所述第二输出是最快的.提高count到100000和编译的版本获胜.
Jon*_*eet 32
如果您要多次重用正则表达式,我会创建它RegexOptions.Compiled并缓存它.让框架在每次需要时解析正则表达式都没有意义.
dev*_*zer 12
对于我机器上的.NET版本,这个答案不再正确.4.0.30319和2.0.50727对IsMatch都有以下内容:
public static bool IsMatch(string input, string pattern)
{
return new Regex(pattern, RegexOptions.None, true).IsMatch(input);
}
Run Code Online (Sandbox Code Playgroud)
'true'值用于名为"useCache"的构造函数参数.所有的正则表达式构造函数最终都是通过这个构造函数链接的,静态函数直接称之为 - 传递"真实".
您了解更多关于BCL博客文章有关优化正则表达式性能突出的静态方法的缓存使用这里.此博客文章还引用了性能测量.阅读一系列关于优化Regex性能的博客文章是一个很好的起点.
我同意Jon的意见,只是为了澄清它看起来像这样:
static Regex regex = new Regex("regex", RegexOptions.Compiled);
Run Code Online (Sandbox Code Playgroud)
它还值得看一下RegexOptions其他可能有用的标志的枚举.