In the Inline::C-Cookbook (0.42), Brian Ingerson writes
I can't think of a real life application where you would want to
generate C code on the fly, but at least I know know how I would
do it. :)
Well, it's not quite real life, but here is a quick late-night example
of dynamic code generation...
(derived from Dawson Engler and Massimiliano Poletto's "A `C Tutorial"
(that's "tick C", a dynamic code generation extension of C),
http://www.pdos.lcs.mit.edu/tickc/papers.html).
A perl loop calling POSIX::pow is an order-of-magnitude slower than a
C loop calling libm's pow() directly. Now, in the (admittedly rare)
case where you are doing a lot of this, and you only need non-negative
integer exponents, and you know ahead of time what your exponent is,
you can get a second oom by first doing this
double pow_for_integer_exp (double base, int exp) {
double result = 1.0;
double square = base;
int bit = 1;
while (bit <= exp) {
if(bit & exp)
result *= square;
bit = bit << 1;
square *= square;
}
return result;
}
and then using
sub create_hot_camel_curry_power {
my($name,$exp) = @_;
my $C = "
double $name (double base) {
double result = 1.0;
double square = base;
";
my $bit = 1;
while($bit <= $exp) {
if($bit & $exp) {
$C .= " result *= square;\n";
}
$bit = $bit << 1;
$C .= " square *= square;\n";
}
$C .= '
return result;
}
';
to make this
double pow_of_42 (double base) {
double result = 1.0;
double square = base;
square *= square;
result *= square;
square *= square;
square *= square;
result *= square;
square *= square;
square *= square;
result *= square;
square *= square;
return result;
}
The hot pow_of_42 is 10x faster than simple pow, and more importantly,
a small integer factor faster than the curry-free pow_for_integer_exp.
That last small integer factor is why folks do dynamic code generation.
If you don't know the number at compile time (of course, this is a bad
example, because everyone knows the number is 42), and the domain is
too big to cover it with a whole bunch of precomputed samples, then
you're either dynamic, or you fall back to a second slower solution.
Which you then have to maintain as well. Perl is now a dynamic code
generation language, albeit one currently with rather slow generation.
A real world application might be to determine the display monitor
gamma at run time, and then bind() a copy of the real libm pow() code,
edited for just that gamma. The gamma won't change very frequently,
and it won't take many megapixel image refreshes to amortize the compile.
So if there is some point in your program which is white hot from
bottleneck friction, ("oh my, it's spending all of its time in line 3
of loop 14"), and you can't crush it out at compile time, then a
dynamically adapting solution written in Perl with Inline::C's runtime
bind(), might run _faster_ than a solution in hand-coded but inert C.
Also of interest is if part of your program is hard coded in C for
speed, but you would really like to be able to tweak it at runtime.
A network stack for instance.
Possible applications are intense matix ops and memory movement,
searching an equation's solution space, dynamic network stack
reconfiguration, algorithm specialization, dynamically modifiable
bytecode interpreters, etc. Not something for everyone, but a
wizzy tool when you need it.
Besides "mere" development convenience and elegance :).
Perl with Inline, and with Inline::C's bind, is a language extension
of C to do dynamic code generation. The first widely available one.
Perl is a great language to code glue.
Now Perl is a nice language to glue code.
Learned of Inline yesterday... Awesome.
Thanks folks,
Mitchell Charity
("...and the proselytizing missionaries of a thousand languages then
came forth and embedded them in the Wall for all to see.")