Type | Platform | Trivial Number | Simple Email Check | Ext Email Check
------------------------------------------------------------------------------
Interpreted | x86 | 4 ms | 26 ms | 31 ms
Interpreted | x64 | 5 ms | 29 ms | 35 ms
Compiled | x86 | 913 ms | 3775 ms | 4487 ms
Compiled | x64 | 3300 ms | 21985 ms | 22793 ms
1,000,000个匹配项-重用Regex对象
Type | Platform | Trivial Number | Simple Email Check | Ext Email Check
------------------------------------------------------------------------------
Interpreted | x86 | 422 ms | 461 ms | 2122 ms
Interpreted | x64 | 436 ms | 463 ms | 2167 ms
Compiled | x86 | 279 ms | 166 ms | 1268 ms
Compiled | x64 | 281 ms | 176 ms | 1180 ms
5条答案
按热度按时间wgeznvg71#
RegexOptions.Compiled
指示正则表达式引擎使用轻量级代码生成(LCG)将正则表达式编译为IL。此编译发生在构造对象期间,并且严重降低了编译速度。反过来,使用正则表达式的匹配速度更快。如果不指定此标志,则将正则表达式视为"已解释"。
举个例子:
它在3个不同的正则表达式上执行4个测试。首先,它测试一个单一一次性匹配(编译与非编译)。其次,它测试重复使用同一个正则表达式的重复匹配。
我的计算机上的结果(在发布版本中编译,未附加调试器)
1000个单一匹配(构造Regex、匹配和释放)
1,000,000个匹配项-重用Regex对象
这些结果表明,在重用
Regex
对象的情况下,编译后的正则表达式的速度最多可提高60%。但是,在某些情况下,构造速度可能会慢3个数量级以上。它还表明,在编译正则表达式时,. NET的x64版本可能会慢5到6倍**。
建议在以下情况下使用编译版本
1.您不关心对象初始化的开销,而需要额外的性能提升(注意,我们在这里讨论的是毫秒的几分之一)。
1.您关心初始化成本,但是多次重用Regex对象,以至于它将在应用程序生命周期中补偿它。
工程中的扳手,Regex缓存
正则表达式引擎包含一个LRU缓存,其中保存了使用
Regex
类上的静态方法测试的最后15个正则表达式。例如:
Regex.Replace
、Regex.Match
等,都使用正则表达式缓存。缓存的大小可以通过设置
Regex.CacheSize
来增加,在应用程序的生命周期中,它随时接受大小的更改。新的正则表达式只被Regex类上的静态助手缓存。如果你构造你的对象,缓存会被检查(为了重用和碰撞),但是,你构造的正则表达式不会被附加到缓存。
这个缓存是一个平凡的LRU缓存,它是用一个简单的双链表实现的。如果你碰巧把它增加到5000,并且在静态助手上使用5000个不同的调用,每个正则表达式构造都会爬网这5000个条目,看看它以前是否被缓存过。检查周围有一个lock,因此检查可能降低并行性并引入线程阻塞。
这个数字被设置得很低,以保护自己免受这种情况的影响,尽管在某些情况下,你可能别无选择,只能增加它。
我的强烈建议是永远不要将
RegexOptions.Compiled
选项传递给静态助手。例如:
原因是你很可能会错过LRU缓存,这将触发一个超级昂贵的编译。另外,你不知道你所依赖的库在做什么,所以几乎没有能力控制或预测缓存的最佳可能大小。
另请参阅:BCL team blog
q9rjltbz2#
BCL团队博客中的此条目提供了一个很好的概述:“Regular Expression performance“。
简而言之,有三种类型的正则表达式(每种执行速度都比前一种快):
1.解释
快速动态创建,缓慢执行
1.编译(您似乎询问的那个)
动态创建速度较慢,执行速度较快(适用于循环执行)
1.预编译
在应用的编译时创建(无运行时创建损失),执行速度快
因此,如果您打算只执行一次正则表达式,或者在应用的非性能关键部分(即用户输入验证)执行正则表达式,则可以选择选项1。
如果你打算在一个循环中运行正则表达式(即逐行解析文件),你应该选择选项2。
如果你有很多正则表达式永远不会为你的应用程序改变,并且被频繁使用,你可以选择选项3。
xtupzzrd3#
值得注意的是,自.NET 2.0以来,正则表达式的性能已经通过未编译正则表达式的MRU缓存得到了提高。Regex库代码不再每次都重新解释相同的未编译正则表达式。
因此,编译后的动态正则表达式可能会带来更大的性能 * 损失 *。除了加载时间更慢之外,系统还使用更多内存将正则表达式编译为操作码。
实际上,当前的建议是要么不编译正则表达式,要么提前将它们编译到单独的程序集中。
参考:BCL团队博客Regular Expression performance [David Gutierrez]
cbwuti444#
下面是一些进一步的阅读
w46czmvw5#
这没有回答问题,但我建议这样做:
这样你就可以两全其美了。因为它是在编译时创建的,所以初始化的时候会很快。使用的时候也会很快。