Thread Regexes: Geschwindigkeitsoptimierung (13 answers)
Opened by GoodFella at 2007-04-06 19:31

bloonix
 2007-04-08 22:13
#75728 #75728
User since
2005-12-17
1615 Artikel
HausmeisterIn
[Homepage]
user image
Hallo GoodFella,

[quote=GoodFella,07.04.2007, 18:32]Ich finde "[ ]+" lesbarer als " +", aber ich werde testen, ob es einen Geschwindigkeitsvorteil bringt.[/quote]
was spricht gegen \s? Das verwendest du doch in der selben
Regex, warum also auch nicht hier? Ich würde es schon ulkig finden,
wenn jemand in der gleichen Regex einmal \w und ein wenig
weiter [a-zA-Z_0-9] verwendet. :)

[quote=GoodFella,07.04.2007, 18:32]Ich dachte, der Modifier o wäre dazu da, den Regexp, wenn er denn Variablen enthält, die sich nicht verändern (wie in meinem Fall), dass Perl den Regex nicht immer neu kompiliert; der gepastete Codepart wird nämlich in einer Schleife ausgeführt.[/quote]
Ja, das ist richtig, allerdings sollte man beachten wo der o-Modifier
verwendet wird. Es nutzt sehr wenig, ihn bei der Variablenzuweisung
zu verwenden, was zum Beispiel PerlProfi versucht:

[quote=PerlProfi,06.04.2007, 17:39]Folgendes machen:
Code (perl): (dl )
1
2
3
4
5
6
7
8
# %search_pattern ist bereits bekannt,
# dieser Teil steht irgendwo, so das er nur einmal ausgeführt wird
my $regexp = qr/^\s*(.*?)[ ]+($search_pattern{'titel'})\s*$search_pattern{'name_vorsatz'}$/sio;

# dann später dein vergleich
#Vorname + Titel + Namensvorsatz:
              elsif ($ba_data{'vorname'} =~ $regexp)
               {
[/quote]

Das bringt rein garnichts an Geschwindigkeitsvorteil, da die Variable
$regexp bei jeden Durchlauf neu initialisiert wird. Wenn mich nichts
täuscht, dann wird die Regex sogar immer wieder kompiliert? Aber dafür
lege ich meine Hand nicht ins Feuer. In der Perldoc gibt es zumindest
kein Beispiel, in dem der o-Modifier mit dem qr//-Operator verwendet
wird, sondern immer nur beim Matchen. Das hat wohl auch seine
Gründe:

Code: (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
25
26
27
28
29
30
31
32
33
34
35
use strict;
use warnings;
use Benchmark;

Benchmark::cmpthese(-1, {
  bad_1 => \&rx_bad_1,
  bad_2 => \&rx_bad_2,
  good  => \&rx_good
});

sub rx_bad_1 {
  for (0..100000) {
     # wird mit jedem schleifendurchlauf kompiliert?
     my $rx = qr/\d+/o;
     1 =~ /$rx/;
  }
}

sub rx_bad_2 {
  for (0..100000) {
     # wird mit jedem schleifendurchlauf kompiliert
     my $rx = qr/\d+/;
     1 =~ /$rx/o;
  }
}

sub rx_good {
  # so ist es richtig, $rx wird ausserhalb der schleife zugewiesen
  my $rx = qr/\d+/;

  for (0..100000) {
     # und in der schleife nur ein einziges mal kompiliert
     1 =~ /$rx/o;
  }
}


       Rate bad_1 bad_2  good
bad_1 4.39/s    --   -3%  -79%
bad_2 4.50/s    3%    --  -78%
good  20.6/s  369%  356%    --


Um bestmögliche Leistung herauszuholen, solltest du alle Regexes vor
der Schleife definieren und in der Schleife den Modifier /o verwenden,
sobald du versuchst zu matchen, so wie es in rx_good() zu sehen
ist.

Gruss,
opi\n\n

<!--EDIT|opi|1176056271-->
What is a good module? That's hard to say.
What is good code? That's also hard to say.
One man's Thing of Beauty is another's man's Evil Hack.

View full thread Regexes: Geschwindigkeitsoptimierung