正则引擎简单分析

由于公司需要用到正则搜索,所以简单看了下正则表达式引擎,根据具体使用环境,选择一款最适合的正则引擎。
正则表达式引擎发展到现在已有十多种,由于只用在linux系统,根据网上推荐,确认PCRE、RE2、C REGEX、C++ REGEX、BOOST REGEX这五个引擎。PERE使用的是perl语言,也排除。C++ REGEX对C++ 11的支持不太好,也排除掉。RE2需要到google官网下载资源(国内的没找到),翻墙失败,也给PASS掉。
最终选取了C REGEX与BOOST REGEX两种正则表达式引擎进行性能测试。
此次测试是根据实际使用情况,使用JSON格式进行测试。

代码

c regex:

/*c regex test

  at20150119*/

#include <regex.h>

#include <iostream>

#include <sys/types.h>

#include <stdio.h>

#include <cstring>

#include <sys/time.h>

using namespace std;

const int times = 1000000;

stringstrBuf("{\"uid\":\"10011\",\"userName\":\"sdy\",\"name\":\"witto\",\"sex\":\"man\",\"identityCode\":\"123552036\",\"telephone\":\"15211012232\",\"qq\":\"888555666\",\"weibo\":\"48sdfs@dsf\",\"cityId\":\"0010\",\"schoolId\":\"1534\",\"subject\":\"hard\",\"ruxuenianfen\":\"20140901\",\"xuezhi\":\"4\",\"dormAddress\":\"xinjiekouwaidajie28hao\",\"roomInfo\":\"4floor506\",\"familyAdress\":\"huoxing\",\"familyPhone\":\"125362356211\",\"contactName\":\"whoami\",\"contactPhone\":\"15200133623\",\"contactRelation\":\"dddddd\"}");

string jsonBuf(

"{\

   \"head\":\

   {\

       \"flowId\":\"10001\",\

       \"subFlowId\":\"001\",\

       \"step\":\"04\"\

   },\

   \"content\":\

   {\

       \"key1\":\"abandenabandenabandenabandenabandenabandenabandenabandenabandenabandenabandenabanden\",\

       \"key2\":\"litterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitter\",\

       \"key3\":\"attheendattheendattheendattheendattheendattheendattheendattheendattheendattheend\",\

       \"key4\":\"rabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbit\",\

       \"key5\":\"111111111111111111111111111111111111111111111111111111111111111111111111111111111111\",\

       \"key6\":\"222222222222222222222222222222222222222222222222222222222222222222222222222222222222\",\

       \"key7\":\"333333333333333333333333333333333333333333333333333333333333333333333333333333333333\",\

       \"key8\":\"444444444444444444444444444444444444444444444444444444444444444444444444444444444444\",\

       \"key9\":\"555555555555555555555555555555555555555555555555555555555555555555555555555555555555\"\

   }\

}");

int main(int argc,char** argv)

{

   //char pattern[64]="\"step\":\"04\"";

   charpattern[64]="\"familyPhone\":\"125362356211\"";

   const size_t nmatch = 10;

   regmatch_t pm[10];

   int z ;

   regex_t reg;

   timeval end,start;

   gettimeofday(&start,NULL);

   long count = 0;

   for(int i = 0 ; i < times; ++i)

    {

regcomp(&reg,pattern,REG_EXTENDED|REG_NOSUB);

       if(!regexec(&reg,strBuf.c_str(),nmatch,pm,REG_NOTBOL))

           count++;

        regfree(&reg);

    }

   gettimeofday(&end,NULL);

   uint time = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec -start.tv_usec;

   cout<<"count:"<<count<<"."<<endl;

   cout<<time/1000000<<" s and"<<time%1000000<<" us."<<endl;

return 0 ;

}

boost regex:

/*c regex test

  at20150119*/

#include <iostream>

#include <sys/time.h>

#include <string>

#include <boost/regex.hpp>

using namespace std;

using namespace boost;

const int times = 1000000; //1 milliontimes

stringstrBuf("{\"uid\":\"10011\",\"userName\":\"sdy\",\"name\":\"witto\",\"sex\":\"man\",\"identityCode\":\"123552036\",\"telephone\":\"15211012232\",\"qq\":\"888555666\",\"weibo\":\"48sdfs@dsf\",\"cityId\":\"0010\",\"schoolId\":\"1534\",\"subject\":\"hard\",\"ruxuenianfen\":\"20140901\",\"xuezhi\":\"4\",\"dormAddress\":\"xinjiekouwaidajie28hao\",\"roomInfo\":\"4floor506\",\"familyAdress\":\"huoxing\",\"familyPhone\":\"125362356211\",\"contactName\":\"whoami\",\"contactPhone\":\"15200133623\",\"contactRelation\":\"dddddd\"}");

string jsonBuf(

"{\

   \"head\":\

   {\

       \"flowId\":\"10001\",\

       \"subFlowId\":\"001\",\

       \"step\":\"04\"\

   },\

   \"content\":\

    {\

       \"key1\":\"abandenabandenabandenabandenabandenabandenabandenabandenabandenabandenabandenabanden\",\

       \"key2\":\"litterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitterlitter\",\

       \"key3\":\"attheendattheendattheendattheendattheendattheendattheendattheendattheendattheend\",\

       \"key4\":\"rabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbitrabbit\",\

       \"key5\":\"111111111111111111111111111111111111111111111111111111111111111111111111111111111111\",\

       \"key6\":\"222222222222222222222222222222222222222222222222222222222222222222222222222222222222\",\

       \"key7\":\"333333333333333333333333333333333333333333333333333333333333333333333333333333333333\",\

       \"key8\":\"444444444444444444444444444444444444444444444444444444444444444444444444444444444444\",\

       \"key9\":\"555555555555555555555555555555555555555555555555555555555555555555555555555555555555\"\

   }\

}");

int main(int argc, char** argv)

{

   //regex pattern("\"step\":\"04\"");

   regexpattern("\"familyPhone\":\"125362356211\"");

   timeval end,start;

   gettimeofday(&start,NULL);

   long count = 0;

   for(int i = 0; i < times; ++i)

    {

       cmatch what;

       if(regex_search(jsonBuf.c_str(), what, pattern))

           count++;

    }

   gettimeofday(&end, NULL);

   uint time = (end.tv_sec-start.tv_sec)*1000000 + end.tv_usec -start.tv_usec;

   cout<<"count:"<<count<<"."<<endl;

   cout<<time/1000000<<" s and "<<time%1000000<<"us."<<endl;

   return 0;

}

测试结果:

 

C REGEX

C REGEX 2

BOOST REGEX

100000

4 s 34818 us

0 s 471980 us

0 s 543303 us

1000000

40s 356427 us

4 s 725609 us

5 s 435129 us

10000000

--

47s 369309 us

54s 479820 us

测试代码忽略错误处理。

由于C REGEX程序运行需要经过三步,编译、执行、释放(代码中标红部分),C REGEX就是把这三步放在循环里面,这样每次查找都会经过这三步。C REGEX 2仅把执行放在循环中,编译与释放放在循环外。

C REGEX执行这步的两个模士REG_NOTBOL与REG_NOTEOL,经过测试后发现速度差不多,所以随机选取了一种。

以上数据为测试结果,取得平均值。C REGEX的千万次测试没有执行,因为10万次与100万次测试与其他两个相差太大,没必要进行千万次测试。

有以上数据可看出,第一列测试数据与后两列相差10倍左右,所以直接淘汰。

第二列测试数据与第三列测试数据相差不多,但是考虑到以后应用场景,每一次查询都是一个完整的过程,而第二列数据只是循环执行这步过程,所以最终选定BOOST REGEX正则表达式引擎。


猜你喜欢

转载自blog.csdn.net/witto_sdy/article/details/43051455