`
lovnet
  • 浏览: 6721941 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
文章分类
社区版块
存档分类
最新评论

RegexOptions.Compiled真的是性能杀手么?

阅读更多

    我们经常胡乱对付着解决问题,欣喜于不大不小的成功,接受失败,<wbr></wbr>并且相信下次会更幸运。

    <wbr></wbr><wbr></wbr>----摩根•琼斯

    "使用正则表达式的时候一定不要使用RegexOptions.<wbr></wbr>Compiled选项,不仅不会加速还会让内存飙升;我们就是这个情况,去掉就好了."<wbr></wbr>这个来自实践而又违反常识的结论让我的朋友很欣喜,<wbr></wbr>显然这个经验要进入他和他团队的知识库了。我写了一个Demo测<wbr></wbr>试了一下,加上RegexOptions.Compiled选项<wbr></wbr>没有带来内存问题,没有印证他所说的结论.

    对于一个问题的梳理我需要从问题上下文开始,而不是一个结论.沟<wbr></wbr>通得知他遇到的情景是这样的:用户提交所有内容要按照有关部门提<wbr></wbr>供的敏感词表使用正则表达式进行敏感词过滤.

    他所处的上下文环境的特点是:

    1.正则表达式构造是依赖于一个敏感词表,而敏感词数量3000<wbr></wbr>左右

    2.他使用正则表达式过程中使用了RegexOptions.<wbr></wbr>Compiled.

    3.这个正则表达式会被反复使用

    于是我调整了Demo模拟他的环境,敏感词表数据使用GUID代<wbr></wbr>替,代码如下:

    Demo
    <!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 Console.WriteLine("---------------------------------------------------");
    2 for (int i = 0; i < 100000; i++)
    3 {
    4 string temp = "kkkkkksdkfjskldjfskljfklahsjdkfhajksdhfjkahsdfjkhasjkdfhjkahdfjkahsdfjkh";
    5 string Filtered = Guid.NewGuid().ToString();
    6 Regex mRegex = new Regex(Filtered, RegexOptions.IgnoreCase | RegexOptions.Compiled);
    7 if (mRegex.IsMatch(temp))
    8 {
    9 //Do nothing
    10 }
    11 }
    12
    13 Console.WriteLine("---------------------------------------------------");
    14


    这下真的内存飙升了

    RegexOptio<wbr></wbr>ns.Compile<wbr></wbr>d真的是性能杀手么?

    关于这个问题,BCL团队已经在其团队博客上给出了详细的解释(<wbr></wbr>点击这里查看),文中从初始化性能和运行时性能考查了三种使用正<wbr></wbr>则表达式的方式;结果归纳如下:

    导致内存飙升的就是下面这个原因:

    Emitting IL with Reflection.Emit loads a lot of code and uses a lot of memory, and that's not memory that you'll ever get back. In addition. in v1.0 and v1.1, we couldn't ever free the IL we generated, meaning you leaked memory by using this mode. We've fixed that problem in Whidbey.


    虽然现在实现了内存释放
    ,但是这种使用方式占用内存还是显而易见<wbr></wbr>的.所以他们建议:

    But the bottom line is that you should only use this mode for a finite set of expressions which you know will be used repeatedly.

    1.表达式是一个有限集合2.表达式集合会被反复使用

    对于朋友的情况,这个过滤相关的表达式肯定是符合这两条的,所以<wbr></wbr>应该使用Compiled的方式,但是考虑到第二种方式对内存的<wbr></wbr>影响以及初始化占用较长时间,所以对他来说最佳选择是使用第三种<wbr></wbr>编译到程序集的方式.关于第三种方式的实现请移步查看这篇文章:<wbr></wbr>"To Compile or Not To Compile"

    -----------------关于这个问题我想说的是-------<wbr></wbr>---------------

    这位朋友的真实情况是他没有在当前的上下文环境中采取正确的使用<wbr></wbr>方式,而他对这个问题的解决仅仅是回退到一个性能较差只不过没有<wbr></wbr>"内存飙升"的方案上,同时RegexOptions.<wbr></wbr>Compiled下了一个性能差的结论.


    去年我在的一件小事:

    数据库服务器异常缓慢,翻了翻日志,我猜测问题可能出现在什么地<wbr></wbr>方,然后修改了程序集做更新,更新期间重启了一下SQL Server服务;然后宣布这个问题解决了;这期间于老师一直通<wbr></wbr>过SQL Server Performance Monitor观察;过了没有多久,于老师指出真正的问题在于有<wbr></wbr>一个存储过程的语句锁表造成了阻塞和更新的程序集没有任何关系;<wbr></wbr>而之所以更新了程序集就见效了是因为更新过程中误打误撞重启了S<wbr></wbr>QL Server,不修改存储过程问题依然存在;果然一段时间后数据<wbr></wbr>库又开始慢了

    那一次,于老师很不高兴,并不是因为那个问题的影响有多大,而是<wbr></wbr>这个问题的解决过程:

  1. 解决问题的过程往往是从""开始,""就是给出解决方案到现<wbr></wbr>象的因果关系;而我只是猜测可能出现在什么地方,但是没有思考为<wbr></wbr>什么是这里,缺少理由
  2. 真正让于老师恼火的在于"大家竟然也就接受了我的解决方案",没<wbr></wbr>有其它人对这个问题进行思考,对这个方案提出质疑

    也就是从这件事情开始
    ,对于一个问题我总是会问自己下面的问题:
    1. 要解决的问题到底是什么,或者说我们怎么定义这个问题?
    2. 我们对这个问题已经了解到什么程度?我是否可以对这个问题进行重<wbr></wbr>述?
    3. 这个问题我们已经解决到了什么程度?我们是不是已经偏离了正确的<wbr></wbr>方向?
    4. 我们采取了什么措施使得问题解决了?
    5. 我们的采取的措施真的就是这个问题的解决方案么?它们存在因果关<wbr></wbr>系么?它为什么有效?
    6. 我们采取的措施是否真正解决了问题?是否带来了新的问题?
  3. 这几个问题,让我少了很多浮躁,多了一些质疑,而且动手验证了很<wbr></wbr>多是是而非的"经验",这个过程让我受益匪浅;


    PS:网上有很多针对SQL ServerSQL语句优化经验,那么这些经验为什么有效?<wbr></wbr>SQL Server2008,它们依然有效么?

坚强2002和你一起回头再说...
分享到:
评论

相关推荐

    RegexOptions.IgnoreCase正则表达式替换,忽略大小写

    RegexOptions.IgnoreCase正则表达式替换,忽略大小写,需要的朋友可以参考一下

    Spider用c#实现 的爬虫算法的实现

    用c#实现 的爬虫算法的实现,并用C# ... Regex MyHrefRegex = new Regex(MyHrefPattern, RegexOptions.IgnoreCase | RegexOptions.Compiled); Match MyHrefMatch = MyHrefRegex.Match(MyPage); while

    正则表达式验证工具,正则表达式校验工具

    正则表达式验证工具 V1.0 本软件主要用于检测正则表达式... 4、选择是否不区分大小写(RegexOptions.IgnoreCase),单行模式(RegexOptions.Singleline)还是多行模式(RegexOptions.Multiline) 5、点击“运行”。

    C# Split分隔字符串的应用(C#、split、分隔、字符串)

    string[] sArray=Regex.Split(str,”js”,RegexOptions.IgnoreCase); foreach (string i in sArray) Response.Write(i.ToString() + “ ”); 输出结果: aaa ccc 2、用多个字符来分隔: 代码如下:string str=”...

    regester.zip

    自动加载上次关闭前运行的最后一组数据 支持树形,表格, 文本等三种结果查看方式 ...可解析类似new Regex("abc", RegexOptions.Singleline | RegexOptions.Multiline)格式的C#代码 支持生成并拷贝C#代码到系统剪切板

    正则表达式测试分析

    支持仅使用表达式里的选中部分进行匹配 自动加载上次关闭前运行的最后一组数据 ...可解析类似new Regex("abc", RegexOptions.Singleline | RegexOptions.Multiline)格式的C#代码 支持生成并拷贝C#代码到系统剪切板

    正则表达式测试工具

    支持仅使用表达式里的选中部分进行匹配 支持树形和表格两种结果查看方式 选中树结点或单元格时自动选中源文本中对应的...可解析类似new Regex("abc", RegexOptions.Singleline | RegexOptions.Multiline)格式的C#代码

    regex正则工具,可复制代码

    RegexTester-正则工具,可复制代码,非常好用 1.功能简介 支持仅使用表达式里的选中...可解析类似new Regex("abc", RegexOptions.Singleline | RegexOptions.Multiline)格式的C#代码 支持生成并拷贝C#代码到系统剪切板

    正则表达式中不区分大小写的写法

    正则忽略大小写 – RegexOptions.IgnoreCase 例如: 代码如下: Str = Regex.Replace(Str, “or”, “”, RegexOptions.IgnoreCase) 会把字符串中的or,Or,oR,OR去掉. 也可以直接在正则表达式内设定相关选项,比如: ...

    C# 过滤HTML标签的几种方法

    /**/ /// /// 去除HTML标记 /// /// 包括HTML的源码 /// 已经去除后的文字 public static string NoHTML(string Htmlstring) { //删除脚本 ...&gt;.*?&lt;/script&gt;", "", RegexOptions.IgnoreCase); //删除HTML

    ajax实现在线无刷新采集

    MatchCollection MC = new Regex(Patrn, RegexOptions.IgnoreCase).Matches(sStr); if (MC.Count != 0) { string[] ArrStr = new string[MC.Count]; for (int I = 0; I &lt; MC.Count; I++) { ArrStr[I] = MC[I]...

    C#基于正则去掉注释的方法示例

    本文实例讲述了C#基于正则去掉注释的方法...\*/, , RegexOptions.IgnoreCase); input = Regex.Replace(input, @^\s*//[\s\S]*?$, , RegexOptions.Multiline); input = Regex.Replace(input, @^\s*$\n, , RegexOptions

    RegexTester.rar

    A tool to write and test regular expressions, generate VB/C# code, and compile assemblies. RegexOptions.Singleline feature added by deerchao.

    C#提取网页中超链接link和text部分的方法

    本文实例讲述了C#提取网页中超链接link和text部分的方法。分享给大家供大家参考,具体...), RegexOptions.IgnoreCase | RegexOptions.Singleline); Match m = re.Match(s); if(m.Success) { string link = m.Groups[hr

    C#信息采集工具实现

    Regex r = new Regex(reg, RegexOptions.Compiled); MatchCollection matches = r.Matches(content); ArrayList a = new ArrayList(); foreach (Match m in matches) { string[] arr = new string[10]; ...

    JavaScript正则表达式中的ignoreCase属性使用详解

    主要介绍了JavaScript正则表达式中的ignoreCase属性使用详解,是JS学习进阶中的重要知识点,需要的朋友可以参考下

    word detection

    Regex regSplit = new Regex(@"\W+|[a-zA-Z0-9]+", RegexOptions.Compiled | RegexOptions.Multiline); StreamReader sr = null; int total = 0; string _filename = ""; public HashSet&lt;string&gt; ...

    asp.net面试题

    ID=$0”, RegexOptions.IgnoreCase) B. Regex.Replace(sUrl, @“/(\d+).aspx”, “/a.aspx?ID=$0”, RegexOptions.IgnoreCase) C. Regex.Replace(sUrl, @“/(\d+).aspx”, “a.aspx?ID=$1”, RegexOptions....

Global site tag (gtag.js) - Google Analytics