由于公司需要用到正则搜索,所以简单看了下正则表达式引擎,根据具体使用环境,选择一款最适合的正则引擎。
正则表达式引擎发展到现在已有十多种,由于只用在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(®,pattern,REG_EXTENDED|REG_NOSUB);
if(!regexec(®,strBuf.c_str(),nmatch,pm,REG_NOTBOL))
count++;
regfree(®);
}
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正则表达式引擎。