Contrary to PHP (if you ever used it), require is the more dynamic
one of the two. Both statements are used to import modules, however use is executed compile
time (ie when the parser runs through the script), and require is executed when the actual line is evaluated.
Generally speaking you should use use
(:-)), because you get the maximum and earliest warning if you referenced an unavailable module. However there are some uses for require, like detecting available modules (as I will discuss shortly in an other post) or reducing memory consumption.
Concrete case: I manage a server which processes files. The processing has conceptually a pipe architecture: a file comes in, a script processes it, puts in in a directory for a second script to process it, which in turn puts in in a third directory for a third script to process it and so on. Until recently the script were activated at regular intervals, cron style. However, in an effort to reduce latency, I redesigned it to work the following way:
- The
scheduler
has the sole role to restart scripts which ended - At the start the script waits for a given period for a synchronization object
- When the period passes or the synchronization object becomes signaled, it starts execution
This means that there are two possible reasons a script can start execution:
- The timeout has passed (just like in the original design)
- An other script signaled that it has provided work for the given script
However one side-effect of the new architecture which I did not anticipate (although it shouldn't be rocket-science) is that processes sit idling around most of the time consuming 20-30MB of memory, because they load all their modules as they start up. The way I resolved this problem was:
Made a minimal module containing the code to wait for the event
Made sure that scripts reference as soon as possible (made the script start like this):
use strict;
use warnings;
use waiter;
wait_for(600);
Converted the import method for other modules to require
. What you need to remember is that:
use Foo;
# is equivalent to
BEGIN {
require Foo;
Foo->import();
}
use Foo qw(foo bar);
# is equivalent to
BEGIN {
require Foo;
Foo->import(qw(foo bar));
}
use Foo (); #not importing anything, not even the default things
# is equivalent to
BEGIN { require Foo; }
This cut down the memory usage from 20-30MB to around 5MB. Woot!
Update: I forgot to mention the use if module from CPAN which is somewhat similar in scope.
Update: As Anonymous correctly points out, for the perfect equivalence between use and require I should put them in "BEGIN" blocks. You can see the difference if you try using the imported things before the actual import (without the BEGIN block it won't work, with the BEGIN block it will work). But that is bad practice in general.
shouldn't
ReplyDeleteuse Foo;
# is equivalent to
require Foo;
Foo->import();
be
use Foo;
# is equivalent to
BEGIN{
require Foo;
Foo->import();
}
@Anonymous: yes, you are correct. I updated the original post. Thank you.
ReplyDelete