http://www.perlmonks.org?node_id=33029

mirod has asked for the wisdom of the Perl Monks concerning the following question:

This is half a question (how can this technique be improved?) and half craft (but with too many comments to fit in the craft mold!)

I thought you might one day need this crude-but-efficient (albeit dangerous) technique to speed-up OO modules without compromising the cleaness of the code.

I usually define accessor methods to every attribute of my objects, even those which are implemented as simple hash fields. Thus I have usually a field and a set_field method for each field. I use those accessor methods even within the module, just in case one day I change the implementation and I move the attribute from a simple field to... something else.

Then in order to get back the speed lost in those method calls, when I install the module I pre-process it and replace the methods by hash access through a simple script:

#!/bin/perl -p # basic substitution # processing the field method is easy s/((\$\w+)->field\b/$1\->\{field\}/g; # the set_field method has an argument, capture it s/s/(\$\w+)->set_field\(([^)]*)\)/$1\->\{field\}= $2/g

The actual code I use is improved to process several fields at once, to allow the object to be an array element (hash element is left as an exercice for the reader), and to perform the replacement only if no other argument is passed to the field method:

#!/bin/perl -p BEGIN { $FIELD="field1|field2|field3"; } s/(\$\w+(?:\[\d\])?)->($FIELD)\b(?!\()/$1\->\{$2\}/g; s/(\$\w+(?:\[\d\])?)->set_($FIELD)\(([^)]*)\)/$1\->\{$2\}= $3/g;

Then I just add a depend item in Makefile.PL;

    'depend' => { 'oo.pm' => "oo.pm.slow\n\tperl speedup oo.pm.slow > oo.pm\n"},

Where oo.pm.slow is the code I edit and maintain while oo.pm is the module that gets installed.

One caveat is that you can't use parenthesis in an argument to the set_field method, although this could be fixed using the latest regexp extensions.

Once that script is written you can also use it to speedup scripts that use the module, with the important drawback that when the implementation changes you will have to re-run the speedup script on all such scripts.