in reply to Macro in perl code?

I find this interesting. There's a related discussion in the Log::Log4perl documentation under section Penalties. The essence is that interpolation (of long arrays) and subroutine calls are relatively expensive in perl, while a simple if ($variable) { .. } is relatively cheap. You may consider not calling your logging subroutine at all unless logging is enabled:
v_print ($message) if ( $volume >= $verbosity );

Furthermore, a Benchmark of the code in question with and without debugging enabled would be interesting to see.

--
Andreas

Replies are listed 'Best First'.
Re^2: Macro in perl code?
by Krambambuli (Curate) on Oct 16, 2007 at 21:44 UTC
    Here is a benchmark attempt for a few variations:
    #!/usr/bin/perl use strict; use warnings; use Benchmark; our $verbosity = 7; our $volume = 1; our $holy_crap = "Hmmmm.. here's the problem!"; timethese(10000000, { 'Name1' => ' v_print0( 1, "Holy Crap = holy_crap\n"); ', 'Name2' => ' v_print0( 1, "Holy Crap = $holy_crap\n"); ', 'Name3' => ' v_print1( 1, sub { "Holy Crap = holy_crap\n" } ); ' +, 'Name4' => ' v_print1( 1, sub { "Holy Crap = $holy_crap\n" } ); ' +, 'Name5' => ' v_print2( 1, \'"Holy Crap = holy_crap\n"\' ); ', 'Name6' => ' v_print2( 1, \'"Holy Crap = $holy_crap\n"\' ); ', 'Name7' => ' if ( $volume >= $verbosity ) { v_print3( "Holy Crap + $holy_crap\n" ) }; ', });
    And here the results:
    Benchmark: timing 10000000 iterations of Name1, Name2, Name3, Name4, N +ame5, Name6, Name7... Name1: 12 wallclock secs (11.24 usr + 0.01 sys = 11.25 CPU) @ 88 +8888.89/s (n=10000000) Name2: 16 wallclock secs (16.08 usr + 0.00 sys = 16.08 CPU) @ 62 +1890.55/s (n=10000000) Name3: 14 wallclock secs (13.93 usr + -0.01 sys = 13.92 CPU) @ 71 +8390.80/s (n=10000000) Name4: 13 wallclock secs (14.10 usr + 0.00 sys = 14.10 CPU) @ 70 +9219.86/s (n=10000000) Name5: 11 wallclock secs (11.26 usr + 0.00 sys = 11.26 CPU) @ 88 +8099.47/s (n=10000000) Name6: 12 wallclock secs (11.00 usr + 0.01 sys = 11.01 CPU) @ 90 +8265.21/s (n=10000000) Name7: 1 wallclock secs ( 1.24 usr + 0.00 sys = 1.24 CPU) @ 80 +64516.13/s (n=10000000)
    Conclusions seem to be, as you mentioned:
  • avoid calling subs in the first place, if possible
  • postpone string interpolation to happen only in the called sub, not before the call

  • The initial surprise diminished a bit after thinking about the benchmarks - but it's good to know it anyway;)
      One can improve performance even further by using constant.
      $ cat 645310.pl use strict; use warnings; use Benchmark qw/ cmpthese /; our $verbosity = 7; our $volume = 1; use constant VERBOSE => 0; cmpthese( -1, { 'Name7' => ' if ( $volume >= $verbosity ) { v_print3( "foo" ) }; ' +, 'Name8' => ' if ( VERBOSE ) { v_print3( "foo" ) }; ' +, } ); sub v_print3 { my $message = shift; print $message; } __END__ $ perl 645310.pl Rate Name7 Name8 Name7 9442579/s -- -74% Name8 35826879/s 279% --
      The whole subroutine call gets optimized away:
      $ perl -MO=Deparse,-x,-p -e 'use constant VERBOSE => 0; if ( VERBOSE ) + { v_print3( "foo" ) }; ' use constant ('VERBOSE', 0); '???'; -e syntax OK
      --
      Andreas