Thread Leerzeichen-Regex lässt StackExchange ausfallen? (27 answers)
Opened by GwenDragon at 2016-07-21 13:24

clms
 2016-07-26 12:04
#185144 #185144
User since
2010-08-29
373 Artikel
BenutzerIn
[default_avatar]
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
2
3
4
5
6
7
8
timethis 100000: 3.81796 wallclock secs ( 3.82 usr +  0.00 sys =  3.82 CPU) @ 26178.01/s (n=100000)
timethis 100000: 1.70095 wallclock secs ( 1.70 usr + 0.00 sys = 1.70 CPU) @ 58823.53/s (n=100000)
timethis 100000: 2.86398 wallclock secs ( 2.87 usr + 0.00 sys = 2.87 CPU) @ 34843.21/s (n=100000)
timethis 100000: 1.70098 wallclock secs ( 1.70 usr + 0.00 sys = 1.70 CPU) @ 58823.53/s (n=100000)
M1A: 100000
M1B: 0
M2A: 100000
M2B: 0

und mit 5.8.8
Code: (dl )
1
2
3
4
5
6
7
8
9
Subroutine Benchmark::mytime redefined at /usr/lib/perl5/5.8.8/Benchmark.pm line 459.
timethis 100000: 23.9664 wallclock secs (23.95 usr + 0.01 sys = 23.96 CPU) @ 4173.62/s (n=100000)
timethis 100000: 1.69792 wallclock secs ( 1.70 usr + 0.00 sys = 1.70 CPU) @ 58823.53/s (n=100000)
timethis 100000: 23.9532 wallclock secs (23.94 usr + 0.02 sys = 23.96 CPU) @ 4173.62/s (n=100000)
timethis 100000: 1.6998 wallclock secs ( 1.70 usr + 0.00 sys = 1.70 CPU) @ 58823.53/s (n=100000)
M1A: 100000
M1B: 0
M2A: 100000
M2B: 0

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?

View full thread Leerzeichen-Regex lässt StackExchange ausfallen?