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

I'm trying to test how long it takes for a particular module to load. I'm trying to use the following code:
#!/usr/bin/perl use Time::HiRes; use Time::HiRes qw ( gettimeofday tv_interval ); my $iterations = 10000; $t0 = [gettimeofday]; foreach (1..$iterations) { use my_module; } $elapsed = tv_interval( $t0, [gettimeofday] ); print "Elapsed Time: $elapsed\n"; print "Iterations: $iterations\n"; print "Mean Time: " . ( $elapsed / $iterations ) . "\n";
This seems to be only loading the module on the first iteration. Is there a way to force the module to "unload".

I know I could simply time the entire script running each time, essentially writing one script to time another script, but I want to avoid timing the parsing of the surronding Perl code, I just want the time for the load of the module.

Replies are listed 'Best First'.
Re: Timing a Module Load
by Fletch (Bishop) on Apr 29, 2005 at 19:48 UTC

    For one thing, use happens at compile time so you're not really timing anything with your code. What you'd really want to do is use require instead and clobber the corresponding entry in %INC before attempting to reload.

    Update: Alternately, load the module source into a scalar and use eval "$source" instead.

      Thanks! I actually figured this out and now have
      do "my_module.pm";
      instead of
      use my_module;
      I think that does the clobber of %INC and forces the reload. My guess is that this differs from eval "$source" solution you mention only in that I'm actually reading the module from disk each time with the "do" solution.
Re: Timing a Module Load
by mda2 (Hermit) on Apr 29, 2005 at 22:45 UTC
      Profiling in perl has a big overhead. You can use it to find hot spots on the code, but not to time things.
Re: Timing a Module Load
by saintmike (Vicar) on Apr 29, 2005 at 20:08 UTC
    The previous responders hit the nail on the head, just in case if you're interested in timing the use: You need to put the starting timer code into a BEGIN block before the use call:
    BEGIN{ $t0 = [gettimeofday]; } use my_module; $elapsed = tv_interval( $t0, [gettimeofday] );
      Not exactly correct... ALL the code has to be in the begin, otherwise other things may happen (uses, other begin blocks) before the tv_interval runs.

                      - Ant
                      - Some of my best work - (1 2 3)

Re: Timing a Module Load
by halley (Prior) on Apr 30, 2005 at 18:18 UTC
    A technique which nobody has mentioned above is simply comparing against a control group. Time a few thousand iterations loading the module,
    % for e in `seq 1000` ; do perl -Mmymodule -e1 ; done
    Then time a few thousand iterations of not loading the module.
    % for e in `seq 1000` ; do perl -e1 ; done
    Subtract the control group timing from the target group timing. What difference do you find?

    --
    [ e d @ h a l l e y . c c ]

Re: Timing a Module Load
by eibwen (Friar) on Apr 30, 2005 at 01:54 UTC

    Is there a way to force the module to "unload".

    I would presume that a use statement which falls out of scope would automatically "unload" the module:

    #!/usr/bin/perl -w use strict; { use Date::Manip; } print Date::Manip::UnixDate(localtime);

    However the above code parses and runs without error, indicating that use isn't limited to a particular scope. Can someone explain why modules aren't (or at least do not appear to be) limited by scope?

      When you "use" a pragma, it gets scoped. But using a module is not scoped. Either way, this is all done during compile time, not run time (even though it may affect the runtime, such as "no warnings qw(uninitialized)").

      So, you use Data::Manip. This is done during compilation. Then, at run time, those braces really have nothing in them (the use being completed at run time only).