標籤: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_COMPboost::regex pattern("commonquery.jsp.*keyName=YwdjywcQueryMain&queryAction=cxywcdj");std::string target ="/YGFMISWeb/faces/query/commonquery/commonquery.jsp?^query/keyName=YwdjywcQueryMain&queryAction=cxywcdj";#endifif(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;}結果如下,不先行編譯模式字串平均情況如下:
[email protected]:~/test$ ./boost_regex_main used: 38 msmatched 10000 times
而先行編譯的情況會好不少:
[email protected]:~/test$ ./boost_regex_main used: 11 msmatched 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_COMPregex_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_COMPif(match_pre_comp(&oRegex, target))#endif#if !PRE_COMPif(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_COMPregfree(&oRegex);#endifprintf("used: %lu ms\n", time_used);printf("matched %d times\n", count);return 0;}結果如下,不先行編譯模式字串平均情況如下:
[email protected]:~/test$ ./c_regex_main used: 52 msmatched 10000 times
先行編譯的情況:
[email protected]:~/test$ ./c_regex_main used: 42 msmatched 10000 times
其實比起長字串下的兩種模式,這也是相差也不算小,主要看百分比,如果規模變大,不先行編譯10000ms,那麼先行編譯就是8000ms。同時可以看出,Boost和C regex在不先行編譯模式字串的情況下,二者相差相對不大(當然,相對的是長字串下的比較)。3.總結下面以表格的方式全面對比一下Boost regex和C regex。
所以,最終我們得到結論,使用Boost regex的庫,並且採取先行編譯模式字串。
關於Boost,C Regex對短目標字串正則匹配的效能分析