eval - efficiency

[email protected] (allan) Mon, 02 Jul 2001 22:22:30 +0200
Newsgroups perl.macperl.anyperl
Message-ID <[email protected]>
hi
please excuse this rather lengthy mail ...

im a bit curious about the eval function in perl.
consider the ready-to-run script below containing 3 different
subroutines which in fact are doing the same, but with different
efficiency. i have included a switch to easily try them all.
the subroutines jobs are to look thru some content for a certain pattern
and when found replace that pattern with a value which it look up inside
a txt.file, called "dbm.txt". this txt file im testing on looks
currently exactly like this:

<tag id=1>:basic=3.00:private=13.00
<tag id=2>:basic=4.00:private=23.00
<tag id=3>:basic=5.00:private=33.00



version1 is pretty much straight forward looping.
version2 is how i thought it should be done with the eval function, as i understand
the pattern(s) then get compiled only once.
version3 is a direct version (in fact it is the printed output of the
eval in version2).

version 3 is slightly faster than version 1, which is considerably
faster than version2.

my only question is, how come the eval version is slower than
version1 (and can i make it faster)?

thanks
allan


#!perl -w

use strict;

my $content  = "
this is various content containg tags like these:
<tag id=1> (probably more content)
<tag id=2> (probably more content)
";

my $cust = "private";
my ($version1Response, $version2Response, $directResponse);
my $switch = 1;

my $start = (times)[0];

for (my $i=0;$i<=300;$i++) {
	if ($switch == 1) {
		$version1Response = normalVersion($content, $cust);
		print $version1Response;
	} elsif ($switch == 2) {	
		$version2Response = evalVersion($content, $cust);
		print $version2Response;
	} else {
		$directResponse = directVersion($content, $cust);
		print $directResponse;
	}
	
}

my $finish = (times)[0];
my $result = $finish - $start;
print "\nthis took $result";


############version 1############

sub normalVersion {
	(my $output, my $customer) = @_;
	open (FILE, "dbm.txt"); 
	while (<FILE>) {
		chomp;
		while (/(<tag[^>]+id=\d+>).+$customer=([^:]+)/g) {
			my $tag = $1;
			my $val = $2;
			$output =~ s/$tag/$val/g
		}
	}
	close(FILE);
	return  $output; 
}

############version 2############

sub evalVersion {
	(my $output, my $customer) = @_;
	my $max = 2; #this will be known
	my ($tag, $val);
	my $code = "open (FILE, \"dbm.txt\");\n";
	$code .= 'while (<FILE>) {';
	$code .= "\nchomp;";
	for (my $j=1;$j<=$max;$j++) {
			$code .= "\n\twhile (/(<tag[^>]+id=$j>).+$customer=([^:]+)/g) {\n";
#fill it with constants
			$code .= "\t\t\$tag = \$1;\n";
			$code .= "\t\t\$val = \$2;\n";
			$code .= "\t\t\$output =~ s/\$tag/\$val/go\n"; #not sure of /o benefit
			$code .= "\t}\n";
	}
	$code .= "}\n";	
	$code .= "close (FILE);\n";
	$code .= "return  \$output;";
	eval $code;
}

##########direct############

sub directVersion {
	(my $output, my $customer) = @_;
	open (FILE, "dbm.txt");
	while (<FILE>) {
	chomp;
		while (/(<tag[^>]+id=1>).+private=([^:]+)/g) {
			my $tag = $1;
			my $val = $2;
			$output =~ s/$tag/$val/go
		}
		while (/(<tag[^>]+id=2>).+private=([^:]+)/g) {
			my $tag = $1;
			my $val = $2;
			$output =~ s/$tag/$val/go
		}
	}
	close (FILE);
	return  $output;
}