2016-06-28 2 views
1

ここでは何が起こっているのか混乱しています。私が見てきたベンチマークのほとんどは、BoostがPerlの近くにいるか、パフォーマンス面でそれを打ち負かすことさえあります。しかし、私のスクリプトでは、Perlの実装は5〜6倍の速さで行われています。Perl C++より高速で動作する正規表現ブーストの実装

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であれば、他のチェックの線形リストをやっていることを少し奇妙に思えるかもしれないことを理解し、私は独立後の各ルールを再フォーマットする必要がためです。それにもかかわらず、私が何かを誤解していない限り、これらの2つのスクリプトはかなり似ています。正規表現の定義のリストを探して、一致するものが見つかるまで他の文字列を続けます。

だから、なぜこれらの結果がどう違うのですか? 100ルール(両方のスクリプトで同じ)& 10,000入力、 .cppの平均は約0.155秒、.plの平均は約0.028秒です。 編集:コンパイラの最適化を実行すると、C++スクリプトは約0.091秒で動作しますが、それでもまだ遅くなります。

洞察が得意です。

+2

最適化でコンパイルしましたか?あなたはデバッグで走っていますか? –

+0

perlバージョンの2番目のパターンは最後に固定されていないことに注意してください。他のものは、私はブーストを使用しませんが、私はよくデフォルトモードECMA正規表現エンジンを使用することを覚えている場合、PCRE正規表現エンジン*(それはより多くの最適化機能を持っています)*を使用しようとしましたか? –

+0

私は./test_script -lrt -lboost_regexでC++をコンパイルして、その実行可能ファイルを実行しています。そして、ありがとう、そのパターンを修正しました。 – Yayahii

答えて

3

コンパイラの最適化設定を有効にすることに加えて、boost::regex_constants::optimizeオプションを使用してください。これは、正規表現ライブラリが最適な正規表現状態マシンを構築するように指示します。あなたはヒープ割り当ての潜在的なオーバーヘッドをしたくないので

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

また、getRuleを参照することではなく、値渡しするようにしてください。

コンパイラが関数をインライン化できることを確認できれば、それが最適です。

また、前述のOalsのように、PerlのようなC++の正規表現では、開始行と終了行のアンカーを使用していません。^... $

+0

これは正にこの部分であるかもしれませんが、この違いのために単独で説明することはできませんか?ありがとう、私はそれを調べます。 – Yayahii