Perl scripts suddenly compiling very slowly - perl

Suddenly, compiling my perl scripts started taking too much time. (About a minute each)
It doesn't really matter what I have in the scripts, what does matter, however, is how many require and use I use.
I think it is in compiling, but I am not sure. The thing is - if I run only the checking part - meaning, perl -c script.h, it takes about the same time.
My question is - how to debug it, how to find out, what exactly is perl doing, to find out what takes so much time?

You can check how long each use an require command takes to load with something like the following (time is a unix/linux command, so on Windows you'll need to keep an eye on your watch):
$ time perl -c -e 'use strict;'
-e syntax OK
real 0m0.122s
user 0m0.000s
sys 0m0.008s
Just change the use/require line for each entry you have to find which one results in the longest time.

If you are on Windows, you could use Process Monitor utility to see disk I/O activity. If you have suspicion on Moose, running isolated script could show what is loaded and when.

Related

Is Perl slower when compiled with DDEBUGGING?

According to this slide from Supercharging Perl - Daina Pettit,
It reads,
Avoid versions of perl compiled with threading or DDEBUGGING unless you know you need them.
I know most distros compile Perl with threading, but my Perl on Debian (as observed with perl -V_ is compiled with -DDEBUGGING=-g does this slow it down?
Perl with debugging enabled is slower.,
Note that a perl built with -DDEBUGGING will be much bigger and will run much, much more slowly than a standard perl.
However, -DDEBUGGING=-g does not enable debugging:
As a convenience, debugging code (-DDEBUGGING) and debugging symbols (-g) can be enabled jointly or separately using a Configure switch, also (somewhat confusingly) named -DDEBUGGING. For a more eye appealing call, -DEBUGGING is defined to be an alias for -DDEBUGGING. For both, the -U calls are also supported, in order to be able to overrule the hints or Policy.sh settings.
and also documented:
Configure -DEBUGGING=-g
Adds -g to optimize, but does not set -DDEBUGGING. (Note: Your system may actually require something like cc -g2. Check your man pages for cc(1) and also any hint file for your system.)
You can test status with: perl -D, if you see the following you do not have -DDEBUGGING,
Recompile perl with -DDEBUGGING to use -D switch (did you mean -d ?)

Making Perl script *run itself* with flags

I'm very new to Perl, and have recently encountered the following problem.
My Perl code must all reside within a single file (it's being called by another program I have no control of).
I now wish to make the script run with a flag (e.g., perl myscript.pl -T for taint mode), although it is initially called without the flag. How can I do that, i.e., how do I "set the flag" from within the Perl file?
One idea that I've had is to make the file launch itself again (after being called without flags), this time with the -T flag (by issuing a shell command such as system($^X, "myscript.pl -T", #ARGS);). Would that work? Any better ideas?
I think you're on the right track. You can make use of the $^{TAINT} variable, and exec instead of system:
exec($^X, $0, '-T', #ARGV) if $^{TAINT} < 1;
This won't work in all cases. For one thing, you'll lose some other command line switches that your script might initially be called with:
perl -I/path/to/some/more/libs -w -MNecessary::Module myscript.pl ...
There are some workarounds to some of these (use warnings or add -w switch to your exec statement above, analyze #INC and %INC to determine what -I and -M switches were added) but the more you can learn about exactly how your script is called, the more you can figure out what workarounds you need to worry about.
Depending on the ... group dynamics in play here, another approach is to exercise some indirect control of the calling program. Go ahead and put -T on the shebang line as #Hunter McMillen and #ThisSuitIsBlackNot suggest, wait for a bug report, and then diagnose the problem as "program not invoked with -T switch" ...

Using Perl modules vs. using system() calls

Quite recently, I wrote a few scripts in Perl for a cPanel plugin in which, though most of the code was in Perl, there was quite a lot of system() commands as well which I used to execute shell commands directly.
I am pretty sure that there are Perl modules that I could have used instead. Keeping in mind the time crunch, I thought using the system command was easier (to complete the project in time). In retrospective, I think that was a bad programming practice.
My question is, is there any tradeoff, memory-wise or otherwise when using Perl's modules and using system() commands. For example, what would be the difference in using:
my $directory = "temp";
mkdir $directory;
and
system ("mkdir temp");
Also, if I am to use Perl modules, wouldn't that involve installing a whole lot of modules in the beginning?
The most obvious economy is that, in the first case, your Perl process is creating the directory, while in the second, Perl is starting a new process that runs a command shell which parses the command line and runs the shell mkdir command to create the directory, and then the child process is deleted. You would be creating and deleting a process and running the shell for every call to system: there is no caching of processes or similar economy.
The second thing that comes to mind is that, if your original mkdir fails, it is simple to handle the error in Perl, whereas shelling out to run a mkdir command puts your program at a distance from the error, and it is far more awkward to handle the many different problems that may arise.
There is also the question of maintainability and portability, which will affect you even if you aren't expecting to run your program on more than one machine. Once you abandon control to a system command you have no control over what happens. I could have written a mkdir that will delete your home directory or, less disastrously, your program may find itself on a system where mkdir doesn't exist, or does something slightly different.
In the particular case of mkdir, this is a built-in Perl operator and is part of every Perl installation. There are also many core libraries that require you to put use Module in your program, but are already installed and need no further action.
I am sure others will come up with more reasons to prefer a Perl operator or module over a shell command. In general you should prefer to keep everything you can within the language. There are only a few cases where you have to run a third-party program, and they usually involve custom software that allows you act on proprietary data formats.

How can I run through a Perl program step by step?

I have a Perl program written by someone else. When I run it, it silently exits without writing anything to the logfile. Is there a way I can run this Perl program step by step, line by line by the interpreter and thus get to see where it terminates?
Yes, there is the Perl debugger which you can invoke with perl -d.
Documentation can be found in perldoc perldebug and perldoc perldebtut.
Probably the most useful commands would be:
s - step into current line.
n - step over current line.
r - step out of current function.
p <expr> - print the expression.
b <line|subnm> - sets a breakpoint
T - produce a stack trace.
c [<line|subnm>] - continue running with optional one-time breakpoint.
h - help (for other commands).
Hachi has the answer. Use the Perl debugger by running perl with the -d flag. For information on how to use the debugger past starting it, see the Perl Debugging Tutorial.
There is a Perl module called "ptkdb" which is a standalone Perl interactive debugger. It works using the Tcl/Tk GUI, so you'll need that, too.
Depending on your OS you'll need to add some required modules.
Invoke it using
perl -d:ptkdb <your script>
If running some Unix/Linux system, you also need an X server.
There are two ways. The first is the one which Hachi and llioin already gave which is using the command-line switch "-d".
Or use an IDE. I am tried and used Komodo IDE which works like charm.

Why doesn't my shell script work when I run it from Perl?

I have this command that I load (example.sh) works well in the unix command line.
However, if I execute it in Perl using the system or ` syntax, it doesn't work.
I am guessing certain settings like environment variables and other external sh files weren't loaded.
Is there an example coding to ensure it will work?
More Updates on coding execution failure (I have been trying with different codes):
push (#JOBSTORUN, "cd $a/$b/$c/$d; loadproject cats; sleep 60;");
...
my $pm = new Parallel::ForkManager(3);
foreach my $job (#JOBSTORUN) {
$pm->start and next;
print(`$job`);
$pm->finish;
}
print "\n\n[DONE] FINISHED EXECUTING JOBS\n";
Output Messages:
sh: loadproject: command not found
Can you show us what you have tried so far? How are you running this program?
My first suspicion wouldn't be the environment if you are running it from a login shell. any Perl script you start (well, any program, really) inherits the same environment. However, if you are running the program through cron, then that's a different story.
The other mistakes I usually make in these situations is specifying the relative paths incorrectly. The paths are fine from the command line, but my Perl script has some other current working directory.
For general advice, see Interact with the system when Perl isn't enough. There's also a chapter in Learning Perl about this.
That's about the best advice you can hope for given the very limited information you've shared with us.