2016-06-28 12 views
1

Ich bin irgendwie verwirrt, was hier passiert. Die meisten Benchmarks, die ich gesehen habe, haben Boost nah an Perl oder schlagen es sogar in Bezug auf die Leistung. In meinen Skripten ist jedoch meine Perl-Implementierung in der Größenordnung von 5-6 mal schneller.Perl Regulärer Ausdruck läuft schneller als C++ Boost Implementierung

Ich öffne Dateien in beiden test_script.cpp & test_script.pl und lesen Sie Zeile für Zeile, ein Array zu füllen. Dann führe ich diese Strings gegen eine Liste von Regex-Definitionen in einer linearen Definition, bis sie übereinstimmen, in diesem Fall passiert nichts (E/A wurde zu Testzwecken entfernt) und dann wird der nächste String verglichen usw., bis wir alle Strings verglichen haben .

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 Methode:

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: Hauptmethode:

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); 

Populate Array-Verfahren:

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

getRule Methode:

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

Ich verstehe, dass es vielleicht ein wenig seltsam erscheinen, dass ich eine lineare Liste, wenn sonst Kontrollen in Perl zu tun, aber das ist, weil ich jede Regel später unabhängig zu formatieren müssen. Unabhängig davon, wenn ich etwas falsch verstehe, sind diese beiden Skripts ziemlich ähnlich - sie schauen sich diese Liste von Regex-Definitionen an, bis sie eine Übereinstimmung gefunden haben, und dann setzen sie mit anderen eingehenden Strings fort.

Warum sind diese Ergebnisse also so unterschiedlich? Für 100 Regeln (für beide Skripte identisch) & 10.000 Eingänge, Der CPP-Wert beträgt etwa 0,155 Sekunden und der Durchschnittswert liegt bei etwa 0,028 Sekunden. Edit: Mit Compiler-Optimierung an Ort und Stelle, arbeitet das C++ - Skript bei etwa 0,091 Sekunden, immer noch langsamer.

Jeder Einblick wird geschätzt.

+2

Haben Sie mit Optimierungen kompiliert? Laufen Sie im Debuggen? –

+0

Beachten Sie, dass das zweite Muster in der Perl-Version nicht am Ende verankert ist. Andere Sache, ich benutze keine Boost, aber wenn ich mich gut erinnere den Standard-Modus verwenden Sie die ECMA Regex-Engine, haben Sie versucht, die PCRE-Regex-Engine * (das hat mehr Optimierungsfunktionen) *? –

+0

Ich kompiliere das C++ mit ./test_script -lrt -lboost_regex und führe dann diese ausführbare Datei aus.Und danke, repariere das Muster. – Yayahii

Antwort

3

Versuchen Sie zusätzlich, die Compileroptimierungseinstellungen zu aktivieren, indem Sie die Option boost::regex_constants::optimize verwenden, die die Regex-Bibliothek anweisen wird, die optimale Regex-Statusmaschine zu erstellen.

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

Auch sicher sein, anstatt nach Wert zu getRule durch Verweis übergeben, weil Sie nicht das Potenzial, Overhead eines Heapzuordnung wollen.

Wenn Sie sicherstellen können, dass der Compiler die Funktion einleitet, wäre das am besten.

Wie oben bereits erwähnt, haben Sie die Anfangs- und Endlinienanker in den C++ Regex-Ausdrücken nicht wie in den Perl-Einsen verwendet.^... $

+0

Dies könnte ehrlich gesagt ein Teil davon sein, obwohl ich nicht sicher bin, dass es allein für diesen Unterschied verantwortlich wäre? Danke, ich werde mich darum kümmern. – Yayahii