首页 > 代码库 > 关于Boost,C Regex对短目标字符串正则匹配的性能分析

关于Boost,C Regex对短目标字符串正则匹配的性能分析

昨天对长目标字符串下的各种正则匹配库性能进行了总结,得出结论是Boost regex性能最佳。今天将其应用到项目当中,果不其然,长字符串匹配带来的性能损失基本没有了,当然,目前规模并不算太大,但是在可预计规模内Boost可以完全达到要求。

不过有一点,在Boost,C同时去除长字符串匹配的影响后,剩下都是短字符串匹配,发现Boost比C好的并不是好很多,例如10000+次短字符匹配中,其中包含匹配成功和不成功的,Boost regex+系统其他模块用时130ms左右,而C regex+系统其他模块140ms左右,二者相差甚小。

当然,这个时候我在项目中用Boost regex是对模式字符串重复编译的,没有预编译。

经过下文的探究,你会发现,昨天文中提到长字符串下C regex模式字符串预编译和不预编译对性能差别影响较小,但是在短字符串下就不能忽视了,对Boost的Regex影响更是甚大。

1.Boost regex 性能分析

首先,我们将昨天的测试字符串换成短字符串,然后在Boost regex下测试不预编译和预编译模式字符串的性能差异。

测试代码如下,通过宏定义#define PRE_COMP ( 0 )表示不预编译,#define PRE_COMP ( 1 )表示预编译,两种模式各循环匹配10000次。

/*
 * Program: 
 *   This program test boost regex performance for short target string 
 * Platform
 *   Ubuntu14.04     g++-4.8.2
 * History:
 *   weizheng     2014.11.07    1.0
 */

#include <boost/regex.hpp>
#include <sys/time.h>
#include <cstdio>

/*
 * choice whether to pre-complie the pattern string, 1 or 0
 */
#define PRE_COMP ( 1 )

const int LOOP_COUNT = 10000;

/************************************ main ************************************/

int main()
{
#if PRE_COMP 
	boost::regex pattern("commonquery.jsp.*keyName=YwdjywcQueryMain&queryAction=cxywcdj");
	std::string target ="/YGFMISWeb/faces/query/commonquery/commonquery.jsp?^query/keyName=YwdjywcQueryMain&queryAction=cxywcdj";
#endif

	/*
	 * record the start time
	 */
	struct timeval tv_start, tv_end;
	gettimeofday(&tv_start, NULL);

	int count = 0;
	for(int i = 0; i < LOOP_COUNT; i++)
	{
#if !PRE_COMP
		boost::regex pattern("commonquery.jsp.*keyName=YwdjywcQueryMain&queryAction=cxywcdj");
		std::string target ="/YGFMISWeb/faces/query/commonquery/commonquery.jsp?^query/keyName=YwdjywcQueryMain&queryAction=cxywcdj";
#endif
		if(boost::regex_search(target, pattern))
		{
			count++;
		}
	}

	/*
	 * record the end time
	 */
	gettimeofday(&tv_end, NULL);
	unsigned long time_used = (tv_end.tv_sec * 1000000 + tv_end.tv_usec - (tv_start.tv_sec * 1000000 + tv_start.tv_usec))/1000;

	printf("used:   %lu ms\n", time_used);
	printf("matched %d times\n", count);

	return 0;
}
结果如下,不预编译模式字符串平均情况如下:

weizheng@weizheng-MS-7798:~/test$ ./boost_regex_main 
used:   38 ms
matched 10000 times
而预编译的情况会好不少:

weizheng@weizheng-MS-7798:~/test$ ./boost_regex_main 
used:   11 ms
matched 10000 times
所以,对于Boost regex来说,一定要使用预编译字符串的模式,不要等到匹配时才编译模式字符串。

2.C regex性能分析

与测试Boost相仿,也是通过宏来选择不预编译模式字符串还是预编译,测试代码如下,其中match_pre_comp()和match()见上一篇文章。
/*
 * Program: 
 *   This program test c regex performance for short target string 
 * Platform
 *   Ubuntu14.04     gcc-4.8.2
 * History:
 *   weizheng     2014.11.07    1.0
 */

#include <sys/time.h>
#include <stdio.h>
#include "regex.h"

/*
 * choice whether to pre-complie the pattern string, 1 or 0
 */
#define PRE_COMP ( 0 )

#define LOOP_COUNT ( 10000 )

/************************************ main ************************************/

int main(void)
{
	char pattern[]="commonquery.jsp.*keyName=YwdjywcQueryMain&queryAction=cxywcdj";
	char target[]="/YGFMISWeb/faces/query/commonquery/commonquery.jsp?^query/keyName=YwdjywcQueryMain&queryAction=cxywcdj";
#if PRE_COMP
	regex_t oRegex;
	if (regcomp(&oRegex, pattern, 0))
		printf("regex complie error\n");
#endif

	/*
	 * record the start time
	 */
	struct timeval tv_start, tv_end;
	gettimeofday(&tv_start, NULL);

	/*
	 * matching
	 */
	int count = 0;
	for(int i = 0; i < LOOP_COUNT; i++)
	{
#if PRE_COMP
		if(match_pre_comp(&oRegex, target))
#endif

#if !PRE_COMP
		if(match(pattern, target))
#endif
		{
			count++;
		}
	}

	/*
	 * record the end time
	 */
	gettimeofday(&tv_end, NULL);
	unsigned long time_used = (tv_end.tv_sec * 1000000 + tv_end.tv_usec - (tv_start.tv_sec * 1000000 + tv_start.tv_usec))/1000;

#if PRE_COMP
	regfree(&oRegex);
#endif
	printf("used:   %lu ms\n", time_used);
	printf("matched %d times\n", count);

	return 0;
}
结果如下,不预编译模式字符串平均情况如下:
weizheng@weizheng-MS-7798:~/test$ ./c_regex_main 
used:   52 ms
matched 10000 times
预编译的情况:
weizheng@weizheng-MS-7798:~/test$ ./c_regex_main 
used:   42 ms
matched 10000 times
其实比起长字符串下的两种模式,这也是相差也不算小,主要看百分比,如果规模变大,不预编译10000ms,那么预编译就是8000ms。
同时可以看出,Boost和C regex在不预编译模式字符串的情况下,二者相差相对不大(当然,相对的是长字符串下的比较)。

3.总结

下面以表格的方式全面对比一下Boost regex和C regex。

所以,最终我们得到结论,使用Boost regex的库,并且采取预编译模式字符串。


关于Boost,C Regex对短目标字符串正则匹配的性能分析