#!/usr/bin/perl -w
use strict;
my %get_prop_str = (
bobn => sub {
local $_ = shift;
my $level = shift || 0;
if ($level == -1) { /([^()]+)\)+$/o; return $1 }
while ($level-- > 0) {
chop;
s/^[^(]+\(//o;
}
return $_;
},
Fatvamp => sub {
my $propstr = shift;
my $level = shift || return $propstr;
my $cnt;
if ($level == -1) {
$propstr =~ /\(([^\(\)]+)\)+/;
return $1;
}
else {
for ($cnt = 0 ; $cnt < $level ; $cnt++) {
$propstr =~ /\((.+)\)/;
$propstr = $1;
}
return $propstr;
}
},
####
Aristotle => sub {
my $str = shift;
my $level = shift || return $str;
$str =~ /.*\((.*?)\)/ and return $1 if $level == -1;
local $_ = substr $str, 0, -$level;
/\G.*?\(/gc while $level--;
return substr $_, pos;
},
####
);
sub original_get_proparg {
my $propstr = shift;
my $level = shift || 0;
my $back = $propstr;
my $cnt;
if ($level == -1) {
$propstr =~ /\(([^\(\)]+)\)+/;
$propstr = $1;
}
else {
for ($cnt = 0 ; $cnt < $level ; $cnt++) {
$propstr =~ /\((.+)\)/;
$propstr = $1;
}
}
return $propstr;
}
use Benchmark;
use Test::More qw(no_plan);
use constant PROP => 'hello(what(is(this(all(about)))))';
use constant RANGE => -1 .. 5;
my %expected = map +($_ => original_get_proparg(PROP, $_)), RANGE;
for my $author (keys %get_prop_str) {
is($get_prop_str{$author}->(PROP, $_), $expected{$_}, "by $author for case $_") for RANGE;
}
Benchmark::cmpthese(-2, { map {
my $func = $get_prop_str{$_};
$_ => sub { $func->(PROP, $_) for RANGE };
} keys %get_prop_str });
__END__
####
ok 1 - by Aristotle for case -1
ok 2 - by Aristotle for case 0
ok 3 - by Aristotle for case 1
ok 4 - by Aristotle for case 2
ok 5 - by Aristotle for case 3
ok 6 - by Aristotle for case 4
ok 7 - by Aristotle for case 5
ok 8 - by bobn for case -1
ok 9 - by bobn for case 0
ok 10 - by bobn for case 1
ok 11 - by bobn for case 2
ok 12 - by bobn for case 3
ok 13 - by bobn for case 4
ok 14 - by bobn for case 5
ok 15 - by Fatvamp for case -1
ok 16 - by Fatvamp for case 0
ok 17 - by Fatvamp for case 1
ok 18 - by Fatvamp for case 2
ok 19 - by Fatvamp for case 3
ok 20 - by Fatvamp for case 4
ok 21 - by Fatvamp for case 5
####
Benchmark: running Aristotle, Fatvamp, bobn for at least 2 CPU seconds...
Aristotle: 2 wallclock secs ( 2.12 usr + 0.01 sys = 2.13 CPU) @ 25239.44/s (n=53760)
Fatvamp: 2 wallclock secs ( 2.10 usr + 0.00 sys = 2.10 CPU) @ 15751.90/s (n=33079)
bobn: 2 wallclock secs ( 2.05 usr + 0.00 sys = 2.05 CPU) @ 22247.80/s (n=45608)
Rate Fatvamp bobn Aristotle
Fatvamp 15752/s -- -29% -38%
bobn 22248/s 41% -- -12%
Aristotle 25239/s 60% 13% --
1..21
####
Aristotle2 => sub {
my $str = shift;
my $level = shift || return $str;
$str =~ /.*\((.*?)\)/ and return $1 if $level == -1;
local $_ = substr $str, 0, -$level;
my $rx = $rx_hash{$level} ||= do {
my $rx = join '', '\A', '(?>.*?\()' x $level;
qr/$rx/;
};
m/$rx/g && return substr $_, pos;
},