Schrift
[thread]11055[/thread]

Viele RegExp Checks auf viele Dateien (Seite 2)

Leser: 1


<< |< 1 2 >| >> 18 Einträge, 2 Seiten
Linuxer
 2007-12-21 16:40
#104099 #104099
User since
2006-01-27
3891 Artikel
HausmeisterIn

user image
Hi,

es kann auch schneller sein, anstatt einen numerischen Quantifier zu benutzen, ein Pattern auszuschreiben:

Code (perl): (dl )
1
2
3
$string =~ m/\w{5}/;
#vs
$string =~ m/\w\w\w\w\w/;

meine Beiträge: I.d.R. alle Angaben ohne Gewähr und auf Linux abgestimmt!
Die Sprache heisst Perl, nicht PERL. - Bitte Crossposts als solche kenntlich machen!
renee
 2007-12-21 19:01
#104101 #104101
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Trotz aller Optimierungen sollte man aber auch die Lesbarkeit nicht vergessen. Denn was nützt ein relativ schnelles Programm, wenn man es nicht mehr warten kann. Optimierungen sind ok, aber man sollte wissen wie und wo man sie macht...
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
styx-cc
 2008-01-02 10:16
#104337 #104337
User since
2006-05-20
533 Artikel
BenutzerIn

user image
Wenn du genug Geld und ein wenig Zeit hast, koennte sich ein Blick in ISBN 978-3-89721-720-1 lohnen.

MfG
Pörl.
Tr0Nix
 2008-01-02 18:50
#104349 #104349
User since
2006-11-21
44 Artikel
BenutzerIn
[default_avatar]
Danke fuer die Tipps. Das O'Reilly Buch werde ich mir wahrscheinlich noch zulegen :).
ptk
 2008-01-03 02:30
#104354 #104354
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
Interessant für dich könnte sein:
* Regexpes zusammenfassen: http://search.cpan.org/dist/Regexp-Assemble/
* perl 5.10.0 - Regexp-Engine könnte schneller sein (z.B. durch Trie-Support)
* Wie nutzt man eine Multiprozessormaschine aus: http://www.tbray.org/ongoing/When/200x/2007/10/30/... (Perl hat hier im Programmierwettbewerb die Nase vorn!)
sid burn
 2008-01-06 16:18
#104444 #104444
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
1) Das wichtigste bei Regexen ist das sie bei einem nicht matchen sich möglichst schnell beenden. Dafür musst du Wissen wie eine Regex Engine einen Treffer findet (also Backtracking muss dir ein Begriff sein). In vielen fällen kannst du dann Backtracking Informationen mit (?>) löschen lassen. Allerdiengs musst du selber Wissen was du da tust. Die falsche verwendung kann dazu führen das deine Regexe nicht mehr das Matchen was du eigentlich wolltest.

2) Weiterhin sollte man den "|" Operator vermeiden wenn es geht. Dieser ist nicht gerade der schnellste. Anstatt 100 Werte mit einem "|" zusammenzufügen ist es schneller die 100 Werte einzelnt auf einen String zu prüfen.

3) Anstatt vieles in einer Regex zu machen sollte man wenn es geht alles auf mehrere Regexe aufsplitten. Wenn man z.B. Whitespace zeichen am Anfang und Ende einer Zeile entfernen möchte kann man das in einem Ausdruck machen oder in zwei aufteilen.

Code: (dl )
1
2
3
4
$string =~ s/^\s*(.*?)\s*$//;

$string =~ s/^\s+//;
$string =~ s/\s+$//;


Die unteren beiden sind viel schneller, auch weil sie eine abbruch bedienung haben. Wenn kein Whitespace Zeichen vorkommt findet keine Substitution statt, oben findet sie immer statt. Und zwei einfache Regexe sind schneller als eine Komplizierte.

3) Wichtig ist es du nutzt Anker. Wenn also etwas nur am Anfang/Ende oder nach etwas stehen darf, dann solltest du diese Sachen hinzufügen. Teilweise musst du es natürlich auch damit deine Regex überhaupt Korrekt arbeitet. Ein Beispiel:

Code: (dl )
1
2
3
4
my $string = "Programm Version 1.2.3 next relase foo bar"

if ( $string =~ m/ ( [\d.]+ ) /x ) { ... }
if ( $string =~ m/ Version ( [\d.]+ ) /x { ... }

Die zweite Regex ist schneller. Bei der ersten regex wird letztendlich jede Position des String auf einer Zahl oder Punkt untersucht und das erste finden wird dann in $1 gespeichert.

Bei der zweiten Regex dient "Version" als Anker. Die Regex Engine ist verdammt Schnell fertige Texte zu Finden, und kann Praktisch direkt nach "Version" anfangen zu Prüfen, ohne die ZEichen davor zu testen. Auch bei einem Fehler nach Version würde es nicht jede Position weiter Testen, da nirgendswo "Version" vorkommt und die Regex im Fehlerfall schneller beendet ist.

Anker können Text ausschnitte sein oder z.B: ^ $ \b


4) Du solltest die Variablen $' $& $`vermeiden.

5) Wenn du die Regexe immer wieder nutzt dann ist gut die Regexe vorzukompilieren und in einem qr// abzulegen. Wenn du nur ein Match machst dann solltest du auch folgende Schreibweise nutzen.

Code: (dl )
$string =~ $vorkompillierte_regexe_mit_qr

anstatt
Code: (dl )
$string =~ m/$vorkompillierte_regexe_mit_qr/


Das erste ist nochmal schneller.

6) Die Option /o:
Diese Option kann deine Performance verbessern wenn Variablen in deiner Regexe auftauchen die Interpoliert werden. Aber auch nur dann. Weiterhin muss die Bedienung erfüllt sein dass diese Variable sich nie mehr ändern soll. Wenn du /o an deiner Regex anhängst dann wird die Regex einmal Kompiliert und für immer so genutzt wie sie beim Kompilieren war. Selbst wenn sich die interpolierten Variablen ändern sollten bleibt die Regex wie beim ersten Kompilieren.

Wenn du also Variablen in einer Regex nutzt die sich definitiv nicht mehr ändern, dann kannst du /o nehmen. Damit muss Perl nicht ständig checken ob sich die Variable verändert hat.

7) Die Funktion study:
Bei bestimmten Anforderungen kannst du auf einen String die Funktion "study" anwenden. Diese Funktion cached bestimmte Teile des Strings und macht das ausführen der Regexe schneller. Allerdiengs gibt es etliche Bedienungen die erfüllt sein müssen damit stidy auch einen Performance schub bringt, anstatt es dein Programm langsamer macht.

Generell funktioniert es so das es Teile deines String abspeichert und Optimierungen abspeichert. Das kostet dich Speichern (kann bis zu viemal so groß sein wie der String selber) und natürlich auch etliches an Rechenkaft die erstmal generiert werden muss. Wenn du study() einfach so auf jeden String anwendest kann es auch dein Programm verlangsamen da der Overhead zur erstellung der Optimierung länger dauert als das reine matchen. Du musst also sicherstellen das du mehr matchest machst als die erzeugung des Overheads.

Weiterhin bringt die Optimierung nur dann etwas wenn sich der zu durchsuchende String nicht mehr verändert. Sollte sich der String verändern. z.B. weil du eine Substitution machst, dann ist die ganze Optimierung zu nichte. Du darfst also nur matchen nicht Substituieren.

Weitere bedienungen die erfüllt sein müssen:
- Die Regexe dürfen die Option /i oder (?i:) darf in den Regexen nicht vorkommen. Diese machen die Optimierung von study kaputt: Du musst also ein "test" so umschreiben: [Tt][Ee][Ss][Tt]
- Man sollte es nicht bei kurzen Suchstrings nutzen. Was genau "kurz" ist hängt sehr von deinen Daten und Regexen ab die du verwendest. Als grobe Faustregel sollte ein String mehrere Killobyte groß sein bis sich eine verwendung lohnt.
- Und nochmal erwähnt: Du musst viele Matchings machen, sonst lohnt sich der Overhead durch Sudy nicht.
- Der zu durchsuchende String darf sich nicht ändern.
- Du solltest study nur dann nutzen wenn in deinen Regexen feste Textteile enthalten sind (also zeichen die definitiv in der Regex vorkommen müssen). Siehe Punkt 3) Anker den genau das ist das was study cached.

Aus deiner Beschreibung heraus kann study() dir wahrscheinlich helfen. Du solltest dann die Dateien komplett im Speicher in einem String einlesen, und study dann auf diesen String anwenden.

8) Nicht wirklich ein Tipp. Aber das bereits genannte Buch Reguläre Ausdrücke kann ich dir nur wärmsten ans Herz legen. Auch wenn es sicherlich untergegangen ist, aber der Punkt 1) ist der allerwichtigste von allen. Du musst deine Regex so schreiben das sie frühstmöglichst erkennen wenn sie auf einen String nicht matchen und sich dann auch sofort beenden, anstatt noch jede Möglich Kombination weiter auszuprobieren. Aber gerade der Punkt ist am schwierigsten zu Erklären. Aber dafür ist das Buch zuständig. Dies erklärt dir das ausführlich.
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
ptk
 2008-01-06 17:59
#104445 #104445
User since
2003-11-28
3645 Artikel
ModeratorIn
[default_avatar]
sid burn+2008-01-06 15:18:09--
2) Weiterhin sollte man den "|" Operator vermeiden wenn es geht. Dieser ist nicht gerade der schnellste. Anstatt 100 Werte mit einem "|" zusammenzufügen ist es schneller die 100 Werte einzelnt auf einen String zu prüfen.

Da sollte man bei perl 5.10.0 umdenken. Regexps mit "|" sind dramatisch schneller geworden. Ich habe hier einen Benchmark, bei dem mit perl 5.8.8 100 einzelne Regexps 10x schneller als ein "|"-Regexp sind. Bei 5.10.0 ist die einzelne "|"-Regexp mehr als 30x schneller als die einzelnen Regexps.

(Benchmark auf Anfrage erhältlich)
Tr0Nix
 2008-01-07 21:55
#104474 #104474
User since
2006-11-21
44 Artikel
BenutzerIn
[default_avatar]
Wow vielen vielen Dank! Echt genial das Forum hier! Euer kompetente Feedback lässt meine Freude an Perl weiter wachsen! Ich nehme mir eure Ratschläge zu Herzen und werds mal mit einzelnen Strings testen.

Die Idee, die ganze Datei in einen einzelnen String einzulesen ist sehr interessant. Insb. da ich so Mehrzeilige Kommentare erkennen kann.

Grüsse
tr0nix
<< |< 1 2 >| >> 18 Einträge, 2 Seiten



View all threads created 2007-12-21 10:51.