RegexOptions.Compiled性能

原文:http://www.cnblogs.com/me-sa/archive/2010/05/19/Is-RegexOptions-Compiled-a-Killer.html

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

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

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

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

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

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

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

Console.WriteLine("---------------------------------------------------");
             for (int i = 0; i < 100000; i++)
             {
                 string temp = "kkkkkksdkfjskldjfskljfklahsjdkfhajksdhfjkahsdfjkhasjkdfhjkahdfjkahsdfjkh";
                  string Filtered = Guid.NewGuid().ToString();
                  Regex mRegex = new Regex(Filtered, RegexOptions.IgnoreCase | RegexOptions.Compiled);
                  if (mRegex.IsMatch(temp))
                  {
                    //Do nothing
                  }
             }

           Console.WriteLine("---------------------------------------------------");

  

这下真的内存飙升了…

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

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

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

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.

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

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.表达式集合会被反复使用

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

-----------------关于这个问题我想说的是----------------------

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

去年我在的一件小事:

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

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

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

      也就是从这件事情开始,对于一个问题我总是会问自己下面的问题:
      1. 要解决的问题到底是什么,或者说我们怎么定义这个问题?
      2. 我们对这个问题已经了解到什么程度?我是否可以对这个问题进行重述?
      3. 这个问题我们已经解决到了什么程度?我们是不是已经偏离了正确的方向?
      4. 我们采取了什么措施使得问题解决了?
      5. 我们的采取的措施真的就是这个问题的解决方案么?它们存在因果关系么?它为什么有效?
      6. 我们采取的措施是否真正解决了问题?是否带来了新的问题?

这几个问题,让我少了很多浮躁,多了一些质疑,而且动手验证了很多是是而非的"经验",这个过程让我受益匪浅;

PS:网上有很多针对SQL Server的SQL语句优化经验,那么这些经验为什么有效?在SQL Server2008中,它们依然有效么?

时间: 2024-08-04 22:16:14

RegexOptions.Compiled性能的相关文章

RegexOptions枚举

在创建Regex类的实例时,构造函数的重载中有一个要求传入RegexOptions的一个枚举值,我相信这个枚举一定非常有用,否则不会要求在构造函数中传入.今天就来看一看这个枚举的作用. 我们干脆把代码敲出来看一看: // 摘要: // 提供用于设置正则表达式选项的枚举值. [Flags] public enum RegexOptions { // 摘要: // 指定不设置选项. None = 0, // // 摘要: // 指定不区分大小写的匹配. IgnoreCase = 1, // // 摘

Unicode转义(\uXXXX)的编码和解码【转】

在涉及Web前端开发时, 有时会遇到\uXXXX格式表示的字符, 其中XXXX是16进制数字的字符串表示形式, 在js中这个叫Unicode转义字符, 和\n \r同属于转义字符. 在其他语言中也有类似的, 可能还有其它变形的格式. 多数时候遇到需要解码的情况多点, 所以会先介绍解码decode, 后介绍编码encode. 下文会提供Javascript C# Java三种语言下不同方法的实现和简单说明, 会涉及到正则和位运算的典型用法. Javascript的实现 解码的实现 1 2 3 fu

当EntityFramework爱上AutoMapper

有时候相识即是一种缘分,相爱也不需要太多的理由,一个眼神足矣,当EntityFramework遇上AutoMapper,就是如此,恋爱虽易,相处不易. 在DDD(领域驱动设计)中,使用AutoMapper一般场景是(Domain Layer)领域层与Presentation Layer(表现层)之间数据对象的转换,也就是DTO与Domin Model之间的相互转换,但是如果对AutoMapper有深入了解之后,就会发现她所涉及的领域不仅仅局限如此,应该包含所有对象之间的转换.另一边,当Entit

提高ASP.NET页面载入速度的方法

前言 本文是我对ASP.NET页面载入速度提高的一些做法,这些做法分为以下部分: 目录 1.采用 HTTP Module 控制页面的生命周期. 2.自定义Response.Filter得到输出流stream生成动态页面的静态内容(磁盘缓存). 3.页面GZIP压缩. 4.OutputCache 编程方式输出页面缓存. 5.删除页面空白字符串.(类似Google) 6.完全删除ViewState. 7.删除服务器控件生成的垃圾NamingContainer. 8.使用计划任务按时生成页面.(本文不

DTO学习系列之AutoMapper(五)----当EntityFramework爱上AutoMapper

有时候相识即是一种缘分,相爱也不需要太多的理由,一个眼神足矣,当EntityFramework遇上AutoMapper,就是如此,恋爱虽易,相处不易. 在DDD(领域驱动设计)中,使用AutoMapper一般场景是(Domain Layer)领域层与Presentation Layer(表现层)之间数据对象的转换,也就是DTO与Domin Model之间的相互转换,但是如果对AutoMapper有深入了解之后,就会发现她所涉及的领域不仅仅局限如此,应该包含所有对象之间的转换.另一边,当Entit

类型查找器 ITypeFinder

NopCommerce为了支持插件功能,以及支持一些自动注册的功能.系统提供了类型查找器.ITypeFinder以及实现类就是提供此功能.通过类型查找器可以查找本程序域中的类,也可以查找整个bin目录下所有动态链接库中类,并把它们注册到类型反转容器中.ITypeFinder以及实现类如下: ITypeFinder接口 /// <summary> /// Classes implementing this interface provide information about types ///

Window系统性能获取帮助类

前言: 这个是获取Windows系统的一些性能的帮助类,其中有:系统内存.硬盘.CPU.网络(个人测试还是比较准的).Ping.单个进程的内存.Cpu.网络(不准).    最初在这个的时候在各种搜索引擎中查询相关资料,发现都有些问题,然后就改了下,总结下,为其他人提供下方便吧. 代码:  代码中最后返回的实体不用管,改为自己的即可. 1 using System; 2 using System.Collections.Generic; 3 using System.Diagnostics; 4

nopCommerce 数据缓存

为了提高一个系统或网站的性能和IO吞吐量,我们一般都会采用缓存技术.当然NopCommerce也不例外,本文我们就来给大家分析一下nop中Cache缓存相关类设计.核心源码及实现原理. 一.Nop.Core.Caching.ICacheManager Nop首先抽象出了一个缓存存储和读取相关管理接口Nop.Core.Caching.ICacheManager. namespace Nop.Core.Caching { /// <summary> /// Cache manager interf

.NET正则基础之——平衡组

1        概述 平衡组是微软在.NET中提出的一个概念,主要是结合几种正则语法规则,提供对配对出现的嵌套结构的匹配..NET是目前对正则支持最完备.功能最强大的语言平台之一,而平衡组正是其强大功能的外在表现,也是比较实用的文本处理功能,目前只有.NET支持,相信后续其它语言会提供支持. 平衡组可以有狭义和广义两种定义,狭义平衡组指.NET中定义的(?<Close-Open>Expression)语法,广义平衡组并不是固定的语法规则,而是几种语法规则的综合运用,我们平时所说的平衡组通常指