Given these two evals which only change Module::FOO()
and FOO()
.
# Symbols imported, and used locally.
eval qq[
package Foo$num;
Module->import();
my \$result = Module::FOO() * Module::FOO();
] or die $@;
# Symbols imported, not used locally referencing parent symbol.
eval qq[
package Foo$num;
Module->import();
my \$result = FOO() * FOO();
] or die $@;
why would the top block take up substantially less space? The script and output are reproduced below,
Script
package Module {
use v5.30;
use warnings;
use constant FOO => 42;
use Exporter 'import';
our @EXPORT = ('FOO');
}
package main {
use v5.30;
use autodie;
use warnings;
$|=1;
say "Our PID is $$";
for my $num ( 0..1e5 ) {
eval qq[
package Foo$num;
Module->import();
my \$result = Module::FOO() * Module::FOO();
] or die $@;
eval qq[
package Foo$num;
Module->import();
my \$result = FOO() * FOO();
] or die $@;
}
say "DONE";
_debug();
}
sub _debug {
open my $fh, "<", "/proc/$$/status";
while ( <$fh> ) {
next unless /Rss/;
print;
}
}
Results
Package (namespace) qualified
RssAnon: 78896 kB
RssFile: 5220 kB
RssShmem: 0 kB
Locally imported
RssAnon: 168180 kB
RssFile: 5496 kB
RssShmem: 0 kB
This is a result of the constant folding inside of Perl. This can be demonstrated with the following example from
haarg
onirc.freenode.net/#perl
,That will result in,
You can see one of them has,
While the other has,
You can get constant folding in both if the module is declared and the import is done in the compiler phase (in the case of a sub compilation), or before the execution in the case of a stringy-eval, like this