Thread Leerzeichen-Regex lässt StackExchange ausfallen?
(27 answers)
Opened by GwenDragon at 2016-07-21 13:24 2016-07-26T15:05:01 renee OK, das ist der Grund warum die Suche nach 'A' am Ende so schnell war. Ich hatte in der Zwischenzeit weiter experimentiert. *$ habe ich weggelassen, weil das ja immer matched, und es stattdessen mit +$ probiert. Insgesamt habe ich jetzt drei Inputstrings mit fünf Regex kombiniert: Die Input-Strings:
Die Regex:
Hier der Code: use strict;
use warnings; use Benchmark qw(:all :hireswallclock) ; our $inputA = "X".(" \t" x 10000)."A"; our $inputB = "X".(" \t" x 10000)."B"; our $inputS = "X".(" \t" x 10000); our $m1A = 0; our $m1B = 0; our $m1S = 0; our $m2A = 0; our $m2B = 0; our $m2S = 0; our $m3A = 0; our $m3B = 0; our $m3S = 0; our $m4A = 0; our $m4B = 0; our $m4S = 0; our $m5A = 0; our $m5B = 0; our $m5S = 0; my $c1A = <<'CODE'; my $s = $inputA; $m1A++ if $s =~ m/\s+A/g; CODE my $c1B = <<'CODE'; my $s = $inputB; $m1B++ if $s =~ m/\s+A/g; CODE my $c1S = <<'CODE'; my $s = $inputS; $m1S++ if $s =~ m/\s+A/g; CODE my $c2A = <<'CODE'; my $s = $inputA; $m2A++ if $s =~ m/(?<=\S)\s+A/g; CODE my $c2B = <<'CODE'; my $s = $inputB; $m2B++ if $s =~ m/(?<=\S)\s+A/g; CODE my $c2S = <<'CODE'; my $s = $inputS; $m2S++ if $s =~ m/(?<=\S)\s+A/g; CODE my $c3A = <<'CODE'; my $s = $inputA; $m3A++ if $s =~ m/\s+$/g; CODE my $c3B = <<'CODE'; my $s = $inputB; $m3B++ if $s =~ m/\s+$/g; CODE my $c3S = <<'CODE'; my $s = $inputS; $m3S++ if $s =~ m/\s+$/g; CODE my $c4A = <<'CODE'; my $s = $inputA; $m4A++ if $s =~ m/(?<=\S)\s+$/g; CODE my $c4B = <<'CODE'; my $s = $inputB; $m4B++ if $s =~ m/(?<=\S)\s+$/g; CODE my $c4S = <<'CODE'; my $s = $inputS; $m4S++ if $s =~ m/(?<=\S)\s+$/g; CODE my $c5A = <<'CODE'; my $s = $inputA; $m5A++ if $s =~ m/\S\s+$/g; CODE my $c5B = <<'CODE'; my $s = $inputB; $m5B++ if $s =~ m/\S\s+$/g; CODE my $c5S = <<'CODE'; my $s = $inputS; $m5S++ if $s =~ m/\S\s+$/g; CODE timethis(100_000,$c1A); print "M1A: $m1A\n"; timethis(100_000,$c1B); print "M1B: $m1B\n"; timethis(100_000,$c1S); print "M1S: $m1S\n"; timethis(100_000,$c2A); print "M2A: $m2A\n"; timethis(100_000,$c2B); print "M2B: $m2B\n"; timethis(100_000,$c2S); print "M2S: $m2S\n"; timethis(100_000,$c3A); print "M3A: $m3A\n"; timethis(100_000,$c3B); print "M3B: $m3B\n"; timethis(100_000,$c3S); print "M3S: $m3S\n"; timethis(100_000,$c4A); print "M4A: $m4A\n"; timethis(100_000,$c4B); print "M4B: $m4B\n"; timethis(100_000,$c4S); print "M4S: $m4S\n"; timethis(100_000,$c5A); print "M5A: $m5A\n"; timethis(100_000,$c5B); print "M5B: $m5B\n"; timethis(100_000,$c5S); print "M5S: $m5S\n"; Das Ergebnis (hier mit Perl 5.18.2) hat mich überraschend: Code: (dl
)
1 timethis 100000: 2.16451 wallclock secs ( 2.17 usr + 0.00 sys = 2.17 CPU) @ 46082.95/s (n=100000) Wenn nach Whitespace vor dem Zeilenende gesucht wird, könnte plötzlich Backtracking ins Spiel kommen. Die Fälle M3A und M3B, bei denen Backtracking auftreten kann, weil es keinen Treffer gibt, sind plötzlich 5 mal langsamer als die vergebliche Suche nach Whitespace vor dem 'A'. Matched die Regex dagegen (=> kein Backtracking) ist die Geschwindigkeit so wie in den vergleichbaren Fällen mit Treffern (M1A, M2A, M4S, M5S). Erschreckend sind die Zeiten für M4A und M4B (Mismatches mit lookbehind als Anker): Fast 100 mal langsamer als im Fall wo nach Whitespace vor 'A' gesucht wird und immer noch 20 mal langsamer als ohne lookbehind Assertion. In den Fällen M5A und M5B entspricht die Zeit dagegen den Fällen M3A und M3B obwohl hier wegen des \S am Anfang der Regex kein Backtracking auftreten kann. |