It's well known that Apache::Registry will load and compile the same
script multiple times when a site contains Apache::Registry scripts in
mutliple directories, symlinked and aliased to different URLs (perhaps as
a means of different levels of access restriction to the same scripts).

An easy (and efficient) way of avoiding this is to map the virtual Apache
perl module name to the underlying file's inode#, instead of its URL.
As an extra bonus, this makes pre-loading scripts a breeze, because you
no longer need to write a complex translation callback to map between
filenames and URLs.

in Registry.pm, the following code:

--------
        my $script_name = $path_info && $uri =~ /\Q$path_info\E$/ ?
            substr($uri, 0, length($uri)-length($path_info)) :
            $uri;

        $script_name =~ s:/+$:/__INDEX__:;

        if ($Apache::Registry::NameWithVirtualHost && $r->server->is_virtual) {
            my $name = $r->get_server_name;
            $script_name = join "", $name, $script_name if $name;
        }

        # Escape everything into valid perl identifiers
        $script_name =~ s/([^A-Za-z0-9_\/])/sprintf("_%2x",unpack("C",$1))/eg;

        # second pass cares for slashes and words starting with a digit
        $script_name =~ s{
                          (/+)       # directory
                          (\d?)      # package's first character
                         }[
                           "::" . (length $2 ? sprintf("_%2x",unpack("C",$2)) : "")
                          ]egx;
-------

can be replaced with

-------
        my ($dev,$inode) = stat(_);     # get fs device and inode numbers
        my $script_name = "::FileAt::Dev${dev}::Inode${inode}"; # generate script name
-------

For increased performance and decreased memory usage, with no duplicate-loading.
And easy pre-loading!

(i didn't make a patch for this since the changes are so trivial, and perhaps
there's a good reason for the current way of doing it that i didn't think of.)


        ~fredrik


Reply via email to