Re: Inlining method/function calls?
by Zaxo (Archbishop) on Jul 26, 2003 at 23:26 UTC
|
There are two cases in perl which sort of correspond to inlining.
One is the folding of constant functions in the compiler's optimization phase. That doesn't give you much direct control, but you can take pains to make perl notice the opportunity. Empty prototypes and constant.pm help there.
The other, mentioned by adrianh, is to invoke the C preprocessor with the -P flag. An example,
#!/usr/bin/perl -P
#define Foo(a) {\
local $, = " ";\
print "defined: ", a, $/;\
}
my ($c, $d, @e, %f) = ('c','d',qw/all in e/);
@f{qw/all in f/} = @e;
Foo($c)
Foo($d)
Foo(@e)
Foo(%f)
After Compline, Zaxo | [reply] [d/l] |
|
|
That is very cool! Right after I ran that snippet, I looked in 3rd Camel to see what it says, but it's quite sparse in what you can do. What is possible? Where could I go for more info, especially examples ...
------ We are the carpenters and bricklayers of the Information Age. Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement. Please remember that I'm crufty and crochety. All opinions are purely mine and all code is untested, unless otherwise specified.
| [reply] |
|
|
The -P flag turns loose the C preprocessor on your source before perl ever sees it. Its behavior is determined by the C standard, at least for the portable parts. The handiest source of information is probably a C primer.
In short, the C preprocessor makes direct textual substitution. with some logic available. I've never needed it for perl, but potentially useful constructs include,
- #include "filename" - inclusion of source from another file.
- #define foo some string or other - substitution macro definition
- #if, #elseif, #else, and friends allow for conditional inclusion of source.
None of this is really necessary to perl.
After Compline, Zaxo
| [reply] [d/l] [select] |
Re: Inlining method/function calls?
by broquaint (Abbot) on Jul 26, 2003 at 22:58 UTC
|
If I understand your question correctly (something like C's inline, but for perl) then I'm afraid the answer is no, you can't inline functions/methods. This is largely due to the complex nature of perl and more directly its dynamic nature and handling of subroutines. Limbic~Region asked this question back in May at Inline subs? and I came up with a filter solution, but as noted in a reply, there are many, many issues with this. Although if I haven't understood your question then you can disregard the above ;)
HTH
_________ broquaint | [reply] |
Re: Inlining method/function calls?
by adrianh (Chancellor) on Jul 26, 2003 at 22:58 UTC
|
Inlining method calls is impossible since they're determined at runtime - you need to know what kind of object $foo is before you know what $foo->method means.
You need the kind of typing hints that Perl6 will be giving us before you can do this sort of optimisation. Sorry :-)
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
| [reply] |
Re: Inlining method/function calls?
by fglock (Vicar) on Jul 27, 2003 at 02:44 UTC
|
# "inline subroutine"
my $inlined = <<'END';
my $expt_len;
## START Inline
# Inlined the ->expected_length method call here.
if ( exists $self->{'expected_length'} ) {
$expt_len = $self->{'expected_length'};
} else {
if( ${$self->{'header_text'}} =~ /L=(?>[^;]+);/ ) {
$expt_len = substr
( ${$self->{'header_text'}},
$-[0] + 2,
$+[0] - $-[0] - 3 );
} else {
$expt_len = undef;
}
}
## END Inline
END
# sub declaration
eval <<'END'
sub body {
my $self = shift;
if ( exists $self->{'uncompressed'} ) {
return $self->{'uncompressed'};
}
unless ( exists $self->{'compressed'} ) {
confess "Record missing body!";
}
END
.$inlined.
<<'END';
$self->{'uncompressed'} =
$self->{'uncompress_function'}( $self->{'compressed'},
$expt_len );
my $retr_len = length ${$self->{'uncompressed'}};
unless ( $expt_len == $retr_len ) {
confess "Uncompressed record length $retr_len did not match expect
+ed "
. "length $expt_len for record $self->{record_number}.";
}
return $self->{'uncompressed'};
}
END
;
| [reply] [d/l] [select] |
Re: Inlining method/function calls?
by BrowserUk (Patriarch) on Jul 28, 2003 at 02:56 UTC
|
Suggestion. Perform the test for existance inline and only call the function if the value must be extracted from the header. The overhead of the function call will likely be lossed in the code of invoking the regex engine.
Question: Why do you use that substr expression? You have captured the value to $1 (if it exists) in order to set @- and @+. Why not just use $1?
Examine what is said, not who speaks.
"Efficiency is intelligent laziness." -David Dunham
"When I'm working on a problem, I never think about beauty. I think only how to solve the problem. But when I have finished, if the solution is not beautiful, I know it is wrong." -Richard Buckminster Fuller
| [reply] |
|
|
Because capturing is the most expensive thing that happens there. On a ten minute program I shaved a minute off by avoiding capturing groups (you mistook (?>...) for a capture block) and using substr instead. A minute is pretty small for the thirty megabyte data set I was working with, I just expected most data sets to be half a gig or more. I picked a simpler example for this code sample - it still illustrates the point (and verified through dprof).
unless ($$buffer =~ m/^H=(?>\d+);/) {
confess "$rec_num was missing the header prefix m/^H=\\d+;/: $$buf
+fer";
}
my $header_length = substr $$buffer, 2, $+[0]-3;
# vs
unless ($$buffer =~ m/^H=((?>\d+));/) {
confess "$rec_num was missing the header prefix m/^H=(\\d+);/: $$b
+uffer";
}
my $header_length = $1;
| [reply] [d/l] |