Thread Leerzeichen-Regex lässt StackExchange ausfallen?
(27 answers)
Opened by GwenDragon at 2016-07-21 13:24
Mein Benchmark funktionierte leider überhaupt nicht, da die Code-Schnipsel in einem Scope ausgewertet wurden, wo $inputA und $inputB nicht sichtbar sind. Es wurde also immer ein undefinierter String durchsucht. Kein Wunder, dass das immer sehr schnell ging.
Ich habe das Programm deshalb gefixt und auch gleich eine Kontrolle eingeführt, dass die Anzahl der erwarteten Matches stimmt. 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 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 use strict; use warnings; use Benchmark qw(:all :hireswallclock) ; our $inputA = "X".(" \t" x 10000)."A"; our $inputB = "X".(" \t" x 10000)."B"; our $m1A = 0; our $m1B = 0; our $m2A = 0; our $m2B = 0; my $c1A = <<'CODE'; my $s = $inputA; $m1A++ if ($s =~ s/[\s\u200c]+A/ A/g); CODE my $c1B = <<'CODE'; my $s = $inputB; $m1B++ if ($s =~ s/[\s\u200c]+A/ A/g); CODE my $c2A = <<'CODE'; my $s = $inputA; $m2A++ if ($s =~ s/(?<=\S)[\s\u200c]+A/ A/g); CODE my $c2B = <<'CODE'; my $s = $inputB; $m2B++ if ($s =~ s/(?<=\S)[\s\u200c]+A/ A/g); CODE timethis(100_000,$c1A); timethis(100_000,$c1B); timethis(100_000,$c2A); timethis(100_000,$c2B); print "M1A: $m1A\n"; print "M1B: $m1B\n"; print "M2A: $m2A\n"; print "M2B: $m2B\n"; Das Ergebnis mit Perl 5.18.2: Code: (dl
)
1 timethis 100000: 3.81796 wallclock secs ( 3.82 usr + 0.00 sys = 3.82 CPU) @ 26178.01/s (n=100000) und mit 5.8.8 Code: (dl
)
1 Subroutine Benchmark::mytime redefined at /usr/lib/perl5/5.8.8/Benchmark.pm line 459. Das Backtracking schein also kein Problem zu sein. Die Version C1B, bei der das Backtracking auftreten könnte, ist nicht langsamer. Zeitfresser scheint das Ersetzen im String zu sein, wobei das zwischen 5.8.8 und 5.18.2 deutlich optimiert wurde. Ich habe das s///g daraufhin durch m//g ersetzt. Praktisch die gleichen Ergebnisse. Das Ersetzen bei einem Treffer kann es auch nicht sein. Ist es das "Reinspringen" in das durch if geschützte Statement? Nächster Versuch: $m1A++ if ($s =~ m/[\s\u200c]+A/g); durch $s =~ s/[\s\u200c]+A/ A/g; ersetzt. Gleiches Ergebnis, außer dass $m1A und $m1B natürlich 0 sind. Kann der Zeitfresser das Kopieren der Treffer in die $MATCH Variable der Regex-Engine sein? |