Why does Perl compile diagnostics.pm if I have no diagnostics in my code?
Asked Answered
E

1

25

When I was looking at the output of Devel::NYTProf v4 for a CGI program, I came across the diagnostics.pm in the report Source Code Files — ordered by exclusive time then name.

diagnostics.pm

First I didn't understand why that would be in the production code. I dug deeper through the report and found out that it was called by main::BEGIN@17. That, in turn, is the following line:

# spent 34µs (26+8) within main::BEGIN@15 which was called: # once (26µs+8µs) by main::RUNTIME at line 15
use strict;
# spent 34µs making 1 call to main::BEGIN@15 # spent 8µs making 1 call to strict::import

# spent 36µs (17+19) within main::BEGIN@16 which was called: # once (17µs+19µs) by main::RUNTIME at line 16
use warnings;

# spent 36µs making 1 call to main::BEGIN@16 # spent 19µs making 1 call to warnings::import

# spent 292ms (171+121) within main::BEGIN@17 which was called: # once (171ms+121ms) by main::RUNTIME at line 17
no diagnostics;
# spent 292ms making 1 call to main::BEGIN@17

# spent 135µs (27+108) within main::BEGIN@18 which was called: # once (27µs+108µs) by main::RUNTIME at line 18
use Carp qw( carp croak );

So this seems to be the culprit. I removed the no diagnostics line, and the call was gone, effectively saving about 300ms of time.

Here's what perldoc use says about the no keyword:

There's a corresponding no declaration that unimports meanings imported by use, i.e., it calls unimport Module LIST instead of import. It behaves just as import does with VERSION, an omitted or empty LIST, or no unimport method being found.

no integer;
no strict 'refs';
no warnings;

So here's my actual question: Am I correct in assuming that if I call no diagnostics, it is actually loaded before it is unimported?

Is the call to no diagnostics similar to this piece of code?

BEGIN {
  require diagnostics.pm;
  diagnostics->unimport;
}

In consequence, is it a bad idea to just unimport stuff that has never been imported, because that actually loads it first?

Eurydice answered 26/11, 2012 at 14:34 Comment(1)
Before anyone points that out: I'm not trying to optimize anything (yet), I'm merely trying to understand what is being called at all.Eurydice
O
22

Am I correct in assuming that if I call no diagnostics, it is actually loaded before it is unimported?

Yes. Its indeed full equivalent to

BEGIN {
  require diagnostics;
  diagnostics->unimport;
}

So no module command actually loads and compiles the module; including executing the code which is not in any sub, in BEGIN block etc; same for all dependencies of given module(for every use/ require inside).

Overliberal answered 26/11, 2012 at 14:38 Comment(1)
In the "ordinary" case, the module is already loaded because you used it somewhere, so the require is a no-op and only the unimport matters. But yes, assuming the module hasn't been required at any previous point, no will do so.Philbin

© 2022 - 2024 — McMap. All rights reserved.