2016-06-28 67 views
1

我對這裏發生的事情感到困惑。我所看到的大多數基準測試都表明Boost已經接近Perl,甚至在性能方面更勝一籌。然而,在我的腳本中,我的Perl實現速度是5-6倍。Perl正則表達式比C++ Boost實現運行速度快

我在test_script.cpp中打開文件& test_script.pl並逐行閱讀,填充數組。然後,我將這些字符串對照線性定義中的正則表達式列表運行,直到它們匹配,在這種情況下沒有任何反應(爲了測試目的而刪除了I/O),然後比較下一個字符串,直到我們比較了所有字符串。

Test_script.pl:

#make incomingList, which contains all incoming strings 
my $start = Time::HiRes::gettimeofday(); 

foreach (@incomingList) { 
    my $inString = $_; 
    &find_pattern($inString); 
} 

my $end = Time::HiRes::gettimeofday(); 
printf("%.6f\n", $end - $start); 

Find_pattern方法:

sub find_pattern { 
    my $URLString = $_[0]; 

    #1 rewrite 
    if($URLString =~ m/^\/stuff\/brands-([^\/]*)\/(.*)?$/) { 

    } 
    #2 rewrite 
    elsif($URLString =~ m/^\/coupons(\/.*)?$/){ 

    } 
    #3 rewrite 
    elsif($URLString =~ m/^\/han\/(.+)$/){ 

    } 
    # ...continues on, there are 100 patterns. 
} 

Test_script.cpp: 主要方法:

populateArray(); 
//make stringArr, which contains all incoming strings 
struct timeval time; 
gettimeofday(&time, NULL); 
double t1=time.tv_sec+(time.tv_usec/1000000.0); 

for(int j =0; j < 10000; j++){ 
    getRule(stringArr[j]); 
} 

gettimeofday(&time, NULL); 
double t2=time.tv_sec+(time.tv_usec/1000000.0); 
printf("%.6lf seconds elapsed\n", t2-t1); 

填入陣列的方法:

static void populateArray(){ 
regexArray[1] = boost::regex ("\\/stuff\\/brands-([^\\/]*)\\/(.*)?"); 
regexArray[2] = boost::regex ("\\/coupons(\\/.*)?"); 
regexArray[3] = boost::regex ("\\/han\\/(.+)"); 
//continues on, 100 definitions. 
} 

getRule方法:

static void getRule(string inQuery){ 
    for(int i =1; i < 100; i++){ 
    if(boost::regex_match(inQuery, regexArray[i])){ 
     break; 
    } 
    } 

我明白,這似乎有些奇怪,我做的,如果在Perl其他檢查線性表,但那是因爲我有獨立之後重新格式化每個規則。無論如何,除非我誤解了某些內容,否則這兩個腳本非常相似 - 他們會查看這個正則表達式列表,直到找到匹配,然後繼續處理其他傳入的字符串。

那麼爲什麼這些結果如此不同呢? 對於100條規則(同樣用於兩個腳本)& 10,000個輸入, .cpp的平均值約爲0.155秒,.pl的平均值約爲0.028秒。 編輯:通過編譯優化,C++腳本的運行時間大約爲0.091秒,仍然較慢。

任何洞察力是讚賞。

+2

您是否使用優化進行編譯?你在調試中運行嗎? –

+0

請注意,perl版本中的第二個模式在末尾沒有錨定。其他的事情,我不使用提升,但如果我記得默認模式使用ECMA正則表達式引擎,您是否嘗試使用PCRE正則表達式引擎*(具有更多優化功能)*? –

+0

我使用./test_script -lrt -lboost_regex編譯C++,然後運行該可執行文件。謝謝,修正了這種模式。 – Yayahii

回答

3

除了打開編譯器優化設置之外,請嘗試使用boost::regex_constants::optimize選項,該選項將指示regex庫構造最優正則表達式狀態機。

static void populateArray(){ 
regexArray[1] = boost::regex ("\\/stuff\\/brands-([^\\/]*)\\/(.*)?", boost::regex_constants::optimize); 
//continues on, 102 definitions. 
} 

此外,請務必按引用傳遞到getRule,而不是價值,因爲你不想要一個堆分配的潛在開銷。

如果您可以確保編譯器內聯函數,那最好。另外,正如厄爾斯在上面所評論的那樣,你還沒有在C++ regex表達式中使用像在Perl中那樣的開始和結束行錨點。^... $

+0

這可以誠實地成爲它的一部分,但我不確定它是否會單獨解釋所有這些差異?謝謝,我會研究它。 – Yayahii