我理解使用RegexOptions.Compiled的好处--它通过使用编译形式的正则表达式而不是在运行时解释它,从而提高了应用程序的执行时间。虽然不建议应用程序使用这种方法,但在启动时已经很慢了。
但如果我的申请能承受启动时间的任何增加-
我不应该使用RegexOptions.Compiled的其他场景是什么?
作为一个注解,我把这个方法叫了好几次-
private static string GetName(string objString)
{
return Regex.Replace(objString, "[^a-zA-Z&-]+", "");
}因此,对“objString”使用不同的值调用此方法(尽管objString的值也可能重复)。
你认为在这里使用RegexOptions.Compiled好/不好吗?任何网络链接都会很有帮助。
谢谢!
编辑
我用两个都测试了我的web应用程序
RegexOptions.Compiled,和Regex实例化为类变量但是我发现我的web应用程序所花费的时间并没有很大的不同--在这两种情况下,我注意到的是,当应用程序第一次加载时,它所花费的时间是连续加载页面所需时间的两倍,这与我是否使用RegexOptions.Compiled无关。
任何评论--
为什么我的web应用程序第一次处理Regex所花费的时间更长,在随后的负载中所花费的时间几乎减少了一半--这里是否有任何内置缓存或其他.net功能在帮助您。不管我是否使用RegexOptions.Compiled,这个东西都是一样的。
发布于 2012-04-01 23:29:46
对于任何像这样的具体性能问题,最好的方法是测试和查看哪种方式更快。
一般来说,编译regex不太可能有多大的好处,除非您经常使用regex,或者是在非常大的字符串上。(或者两者都是)我认为,在您确定存在性能问题并认为这可能会有所帮助之后,尝试更多的是优化,而不是随机尝试。
有关RegexOptions.Compiled缺点的一些一般性讨论,请参阅杰夫·阿特伍德的这篇博文;它非常古老(从.NET Framework1.1时代起),但据我所知,自编写以来,主要的相关事实都没有改变。
发布于 2012-04-01 23:53:53
需要考虑的两件事是,RegexOptions.Compiled占用了CPU时间和内存。
考虑到这一点,基本上只有一个实例应该是而不是使用RegexOptions.Compiled:
可以说,在沙中有太多的变量来预测和画一条线。确定最佳方法确实需要测试。或者,如果您不想进行测试,那么在不使用Compiled之前不要使用它。
现在,如果您确实选择了RegexOptions.Compiled,那么重要的是不要浪费它。
通常,最好的方法是将对象定义为可以反复使用的静态变量。例如..。
public static Regex NameRegex = new Regex(@"[^a-zA-Z&-]+", RegexOptions.Compiled);这种方法的一个问题是,如果您在全局声明它,那么如果您的应用程序不总是使用它,或者在启动时不使用它,那么它可能是一种浪费。因此,一种稍微不同的方法是使用懒惰加载,正如我在昨天写的文章中描述的那样。
在这种情况下会是这样的..。
public static Lazy<Regex> NameRegex =
new Lazy<Regex>(() => new Regex("[^a-zA-Z&-]+", RegexOptions.Compiled));然后,只要您想要使用这个正则表达式,只需在第一次访问它时实例化它,就直接引用NameRegex.Value。
现实世界中的RegexOptions.Compiled
在我的几个站点上,我使用了ASP.NET MVC的Regex路由。这个场景是对RegexOptions.Compiled的完美使用。这些路由是在web应用程序启动时定义的,然后只要应用程序继续运行,这些路由就会被用于所有后续请求。因此,这些正则表达式被实例化和编译一次,并重复使用数百万次。
发布于 2012-04-02 03:59:21
在BCL博客文章中,编译使启动时间增加了一个数量级,但随后的运行时却减少了大约30%。使用这些数字,应该考虑对模式进行编译,您需要对其进行30次以上的评估。(当然,与任何性能优化一样,这两种备选方案都应衡量其可接受性。)
如果性能对于重复调用的简单表达式至关重要,则可能希望完全避免使用正则表达式。我试着运行一些变体,每次运行大约500万次:
注:编辑自上一版本,以纠正正则表达式。
static string GetName1(string objString)
{
return Regex.Replace(objString, "[^a-zA-Z&-]+", "");
}
static string GetName2(string objString)
{
return Regex.Replace(objString, "[^a-zA-Z&-]+", "", RegexOptions.Compiled);
}
static string GetName3(string objString)
{
var sb = new StringBuilder(objString.Length);
foreach (char c in objString)
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '-' || c == '&')
sb.Append(c);
return sb.ToString();
}
static string GetName4(string objString)
{
char[] c = objString.ToCharArray();
int pos = 0;
int writ = 0;
while (pos < c.Length)
{
char curr = c[pos];
if ((curr >= 'A' && curr <= 'Z') || (curr >= 'a' && curr <= 'z') || curr == '-' || curr == '&')
{
c[writ++] = c[pos];
}
pos++;
}
return new string(c, 0, writ);
}
unsafe static string GetName5(string objString)
{
char* buf = stackalloc char[objString.Length];
int writ = 0;
fixed (char* sp = objString)
{
char* pos = sp;
while (*pos != '\0')
{
char curr = *pos;
if ((curr >= 'A' && curr <= 'Z') ||
(curr >= 'a' && curr <= 'z') ||
curr == '-' || curr == '&')
buf[writ++] = curr;
pos++;
}
}
return new string(buf, 0, writ);
}独立执行500万个随机的ASCII字符串,每个字符串30个字符,一致地给出以下数字:
Method 1: 32.3 seconds (interpreted regex)
Method 2: 24.4 seconds (compiled regex)
Method 3: 1.82 seconds (StringBuilder concatenation)
Method 4: 1.64 seconds (char[] manipulation)
Method 5: 1.54 seconds (unsafe char* manipulation)也就是说,编译为这种模式的大量评估提供了大约25%的性能效益,第一次执行速度大约慢了3倍。对底层字符数组进行操作的方法比编译的正则表达式快12倍。
方法4或方法5可能比正则表达式提供一些性能好处,而其他方法可能提供其他好处(可维护性、可读性、灵活性等)。这个简单的测试确实表明,在这种情况下,编译regex比对大量评估解释regex有一定的性能好处。
https://stackoverflow.com/questions/9969158
复制相似问题