Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?

exec vs. backtick-and-assign performance

by apotheon (Deacon)
on Nov 12, 2006 at 08:40 UTC ( #583547=perlquestion: print w/replies, xml ) Need Help??

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

I have a nice, simple question, though the answer may not be as simple. I really don't know. First, two code snippets.

Snippet one:

exec('/etc/init.d/networking restart');

Snippet two:

my $output = `/etc/init.d/networking restart`; print $output;

So, with those in mind -- why does the backtick version take an age and a half to run, while the /etc/init.d/networking restart that picks up where exec() left off is pretty much instantaneous? I don't imagine the assignment can be taking that long, though I suppose I could for some reason be mistaken in such an assumption.

print substr("Just another Perl hacker", 0, -2);
- apotheon
CopyWrite Chad Perrin

Replies are listed 'Best First'.
Re: exec vs. backtick-and-assign performance
by Joost (Canon) on Nov 12, 2006 at 11:05 UTC
    note that backticks will have to wait for the program to finish and all buffers to be flushed before giving the output, while exec() will just switch to the new program and should be inherently faster than backticks; backticks uses pipes / fork / exec (oh yes, and the shell, as jwkrahn said) to accomplish its magic.

    Also note that the two programs aren't at all equivalent, since a successful call to exec() never returns. (You probably know that, but still).

      It still seems odd to me that the code called by exec() runs basically instantly while using backticks it literally takes several minutes to complete the task and print the output. There must be something I'm overlooking.

      From what you said, it sounds like backticks actually use the exec() function -- unless you meant something else. Is that the case?

      "the two programs aren't at all equivalent, since a successful call to exec() never returns. (You probably know that, but still)."
      Yeah, I was aware of that, and that's one of the reasons I tried the backticks first (in case I ended up doing more after running the shell command). It looks like I'll just have to make sure running that command is the absolute last thing the script does, unless I want to either write a lot more code to get the same result as intended with backticks (but faster) or suffer some really unacceptable performance lags on a simple admin script.

      print substr("Just another Perl hacker", 0, -2);
      - apotheon
      CopyWrite Chad Perrin

        How long does it take to run the command manually? It might just take very long to finish.

        backticks will wait for the program to end before returning the output, so if the program just takes a long time to stop, you won't see any output since you're capturing it with the backticks. exec will just replace the current program with the new one, so any output of the command will be printed immediately, even if the program is still running.

        by the way, if you're not doing anything with the output except printing you could also use system(), which doesn't capture the program's output, so any output will also be printed immediately (while the program is running, before system() returns).

        About backticks using exec() - exec() is the only way to start a new program in unix. system(), backtics, piped open etc all use exec() behind the scenes. Calls that execute a command and return do a fork first, then call exec() in the child process. That's why exec() should always be the fastest. Not that you'd normally notice the speed difference - fork() is pretty fast (it has to be - it's the only way to start a new process).

Re: exec vs. backtick-and-assign performance
by jwkrahn (Monsignor) on Nov 12, 2006 at 09:18 UTC
    The only difference I can see is that exec runs the command directly while the backticks invoke the shell and the shell runs the command.

    If you want the command's STDOUT then try using open like:

    my $output = do { open my $fh, '-|', '/etc/init.d/networking', 'restart' or die "Can +not open pipe from '/etc/init.d/networking' $!"; local $/; <$fh> };
Re: exec vs. backtick-and-assign performance
by sgifford (Prior) on Nov 13, 2006 at 03:41 UTC
    That's very odd. While backticks will be slower than exec, it shouldn't be that much slower; definitely less than a 1-second difference unless there's a lot of output.

    Try tracing the program's execution with strace or truss to see what's happening differently between the two.

    It's possible that something in the script is detecting that it's run from the command-line (by noticing that STDIN is a terminal) and doing it's work in the background, or something like that.

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://583547]
Approved by planetscape
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others scrutinizing the Monastery: (4)
As of 2021-06-13 09:23 GMT
Find Nodes?
    Voting Booth?
    What does the "s" stand for in "perls"? (Whence perls)

    Results (54 votes). Check out past polls.