zoukankan      html  css  js  c++  java
  • 浅谈提升C#正则表达式效率

     摘要:说到C#的Regex,谈到最多的应该就是RegexOptions.Compiled这个东西,传说中在匹配速度方面,RegexOptions.Compiled是可以提升匹配速度的,但在启动速度上,使用了RegexOptions.Compiled情况下,通常会使启动速度慢许多,据说最多是60倍。

      说到C#的Regex,谈到最多的应该就是RegexOptions.Compiled这个东西,传说中在匹配速度方面,RegexOptions.Compiled是可以提升匹配速度的,但在启动速度上,使用了RegexOptions.Compiled情况下,通常会使启动速度慢许多,据说最多是60倍。

      进行一组测试,有测试数据,才有讨论依据。

      第一步,帖上测试硬件信息(呵呵,硬件有点烂:()

      第二步,

      a.测试在没有使用RegexOptions.Compiled项时候的情况,随意使用一些内容,然后循环一万次实例化正则表达式对象来匹配这些内容。

    代码
    protectedvoid Page_Load(object sender, EventArgs e)
    {
    WebClient webClient
    =new WebClient();
    string content = webClient.DownloadString("http://www.cnblogs.com/tmyh/archive/2010/09/29/sqlindex_01.html");

    Stopwatch watcher
    =new Stopwatch();
    watcher.Start();

    int i =10000;
    while (i >0)
    {
    Regex rgx
    =new Regex("<div>.+?</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
    bool b1 = rgx.IsMatch(content);

    Regex rgx2
    =new Regex("<p>.+?</p>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
    bool b2 = rgx2.IsMatch(content);

    i
    --;
    }
    Response.Write(
    string.Concat("<div>", watcher.Elapsed.TotalSeconds.ToString("f7"), "</div>"));
    }

      执行发现,内存使用情况为39,760K。输出的执行时间为3.7954446秒(刷了几次,取最快的那次)

      b.测试在使用了RegexOptions.Compiled项时候的情况,随意使用一些内容,然后循环一万次实例化正则表达式对象来匹配这些内容。

    代码
    protectedvoid Page_Load(object sender, EventArgs e)
    {
    WebClient webClient
    =new WebClient();
    string content = webClient.DownloadString("http://www.cnblogs.com/tmyh/archive/2010/09/29/sqlindex_01.html");


    Stopwatch watcher
    =new Stopwatch();
    watcher.Start();

    int i =10000;
    while (i >0)
    {
    Regex rgx
    =new Regex("<div>.+?</div>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
    bool b1 = rgx.IsMatch(content);

    Regex rgx2
    =new Regex("<p>.+?</p>", RegexOptions.IgnoreCase | RegexOptions.Singleline | RegexOptions.Compiled);
    bool b2 = rgx2.IsMatch(content);

    i
    --;
    }
    Response.Write(
    string.Concat("<div>", watcher.Elapsed.TotalSeconds.ToString("f7"), "</div>"));
    }

      执行发现,内存使用情况为42,956K。输出的执行时间为43.3090937秒(刷了几次,取最快的那次)

      从a和b的测试中发现,不妥当地使用此选项,效率是极其低下的,尤其如果在WEB程序上,如果这个页面有大流量请求的话,那会有点不堪设想。我们在正常使用中,极大量文本处理的情况似乎比较少出现,基本上不能体现出RegexOptions.Compiled的所在匹配速度优势,所以通常建议不使用此项。(当然,在正常情况下,我们也不会在每个循环中都new一个正则表达式对象,我们可能会选择static一个)

      第三步,使用传说中的Regex.CompileToAssembly来编译正则表达式,再进行测试。这个,得自己写个编译小程序,帖上本人自己写的一个。点击下载

      与第二步相同的正则表达式Pattern,用这个工具生成dll后,引用到项目。测试执行,发现执行的内存使用情况与第二步的a差不多,速度也相差不多。当然,在这里,这种测试方案,可能看不出这种预编译的正则表达式的效率优点,事实上,它应该能够有更高的执行效率与匹配速度,最好使用多线程与多请求来进行测试。

      在此将其封装到DLL中,这将使最终的程序占用的内存更少,而不必装载使用RegexOptions.Compiled编译正则表达式的包,装载的速度也就得到了提升,同时也拥有了RegexOptions.Compiled的匹配速度优势。另外,也提高了需要一直复用的正则表达式的复用率。缺点,就是比较麻烦,而且只有固定的正则表达式能够这样使用。(关于如何使用Regex.CompileToAssembly,似乎也没多少能够解说的,就三两行代码,下载便知)

      似乎并无深入谈到原理,不过,也并不重要,我们只要经过测试,知道怎么使用能够更好就行了。在此,个人的建议是,通常都不要使用RegexOptions.Compiled,即使要在代码中使用,也应该使用static变量。

      如果真有那么大文本要用的时候,我相信,这个正则表达式也不可能是动态的,固定的正则,我们就使用Regex.CompileToAssembly来先编译成DLL再引用到项目中,即能提供效率,也提高了复用率。

  • 相关阅读:
    Ansible批量更新远程主机用户密码
    国外程序员推荐:每个程序员都应该读的非编程书
    FindFriendsServer服务搭建
    Android JNI HelloWorld实现
    2014年4月读书单
    jQuery 之父:每天写代码
    QT210 Android4.0源码编译和烧录文档整理
    Android系统分区理解及分区目录细解
    Android组件Spinner使用
    使用事件驱动模型实现高效稳定的网络服务器程序
  • 原文地址:https://www.cnblogs.com/rainbowzc/p/3584894.html
Copyright © 2011-2022 走看看