Thread Performance Problem mit Perl bei RegEx (34 answers)
Opened by nomoresecrets at 2009-05-11 17:16

sid burn
 2009-05-12 01:19
#121507 #121507
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
2009-05-11T17:07:32 topeg
mit dem Code:
Code (perl): (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/usr/bin/perl

use strict;
use warnings;

my $file='test.random.txt';

# regexp vorkompilieren
my $regexp=qr/--TEST--/o;

# vernünftige Fehlermeldung
open(TRACEFILE, '<',  $file ) or die "cannot open $file $!\n";

# vor der Schleife definieren
# das redefine in der Schleife bremst aus
my $found=0;
my $in_line;

while ($in_line = <TRACEFILE>)
{
  $found++ while($in_line =~ m/$regexp/gc);
  #$found++ if($in_line =~ m/$regexp/);
}
print "Anzahl Treffer: $found\n";


bekomme ich:

Habe die testdaten ebenfalls so angelegt so wie du es gemacht hast. Bei mir dauert das ganze mit diesem geposteten Code ca. 8 reale Sekunden zum durchlaufen. Auch nach ca. 10 maligen ausführen, von daher da ist auszugehen das schon alles wenn gecached ist.

Allerdiengs kann ich die laufzeit um fast 50% reduzieren indem ich an der Regex einfach die Option "/o" anhänge. (sinkt dann auf 4.4 reale sekunden)

Das ganze mit Perl 5.10 in Debian Lenny. Ich habe allerdiengs noch ein selbst kompiliertes Perl 5.10.0. Das benötigt nur "3.7 reale sekunden". Das selbst kompilierte hat kein "ihtread" support. Das eingebaute in Debian hat es.

Ob es allerdiengs nur an dem ithread support liegt oder nicht noch an etwas anderen weiß ich so nicht. Müsste ich nochmal selber kompilieren mit ithread.


Ansonsten wenn eine variable in einer Regex interpoliert so muss bei jedem! aufruf der Regex vorher geprüft werden ob sich die variable geändert hat, was eine menge checks sind. Mit der Option /o wird die Regex nur einmalig kompiliert, auch wenn sich der Inhalt der variable verändert bleibt dann das enthalten was beim ersten ausführen drin war.

Also das /o muss an der while schleife angehangen werden.

Code: (dl )
$found++ while($in_line =~ m/$regexp/gco)


Das hier ist übrigens total sinnlos:

Code: (dl )
my $regexp=qr/--TEST--/o;


Eine Regex wird bei Perl sowieso schon vor der Ausführung nur einmalig kompiliert. das /o hat nur einen effekt wenn eine variable in der Regex interpretiert wird.

Bei der while Schleife wird die variable nur einmalig interpoliert und nie wieder auch wenn sich der inhalt ändert, wo anders hat das keine auswirkung. In diesen Fall ist das eine gültige Optimieren, da sich der Inhalt ja wirklich nie ändert.


----


Mit deinem zweiten Beispiel dauert es bei mir schon fast ziemlich genau 1 reale sekunde, sogar immer etwas weniger.

Mit /o an der while schleife sinkt die laufzeit auf 0.6 sekunden reale zeit

Beides Debian Lenny version. Selbst kompiliertes ohne /o macht: 0.88 sekunden

Selbst kompiliert /o an while schleife: 0.65 sekunden

Hier scheint also wohl die grenze des I/O erreicht zu sein.

---

Deine letzte version mit "forks" wird dann wieder langsamer.

Debian Lenny Perl: 1.4 sek
Selbstkompiliertes Perl: 1.4 sek (ja der gleiche wert)


Aber ehrlich gesagt würde ich mich wundern wenn es schneller sein würde. Eigentlich zeigen deine tests ja deutlich das es nicht an der CPU liegt sondern am I/O. ein simples <FH> also zeile für zeile fetchen ist zu ineffektiv, mit deinem buffer wird es schneller da mehr auf einmal eingelesen wird. Bei deiner letzten lösungen macht Forken einfach einen Overhead, und I/O wird anscheind sowieso schon vollkommen ausgereizt.

Meine CPU:
Intel Core 2 Duo @ 2 x 3.0Ghz

EDIT:
Diese 10x10 Pixel Editier Box treibt mich zum wahnsinn!!!
Last edited: 2009-05-12 01:53:43 +0200 (CEST)
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de

View full thread Performance Problem mit Perl bei RegEx