in reply to I thought I found a good reason to use backticks in a void context, but I was wrong.

almut, thanks for the idea. I have to admit, I am very wary of closing STDOUT, even if the job is running in cron.

In keeping with my offer, I tried a solution using Net::Ping, which, indeed, looks like exactly what I am looking for, as talexb mentioned.

Here are some preliminary results. I used

#some stuff like use strict, etc. Readonly my $udp_pinger => Net::Ping->new('udp',1); #other stuff, then beginning of loop my $t0 = [ gettimeofday() ]; `ping -q -w 1 -c 1 $host`; die if ($?); my $e0 = tv_interval($t0); print "Ping with backticks took $e0 seconds"; $t0 = [ gettimeofday() ]; $udp_pinger->ping($host) || die "udp ping failed for $host"; $e0 = tv_interval($t0); print "Ping with Net::Ping took $e0 seconds"; print ".."; #end of the loop
I put the return value checks in the timed segments to make the comparison as "fair" as possible. Also note that the program is a loop over 18 distinct hosts, not the same host repeatedly.

Results:

Ping with backticks took 0.004804 seconds
Ping with Net::Ping took 0.002682 seconds
..
Ping with backticks took 0.005873 seconds
Ping with Net::Ping took 0.001528 seconds
..
Ping with backticks took 0.005679 seconds
Ping with Net::Ping took 0.001115 seconds
..
Ping with backticks took 0.005465 seconds
Ping with Net::Ping took 0.001108 seconds
..
Ping with backticks took 0.005369 seconds
Ping with Net::Ping took 0.001098 seconds
..
Ping with backticks took 0.005465 seconds
Ping with Net::Ping took 0.001521 seconds
..
Ping with backticks took 0.006113 seconds
Ping with Net::Ping took 0.001071 seconds
..
Ping with backticks took 0.005269 seconds
Ping with Net::Ping took 0.001227 seconds
..
Ping with backticks took 0.005122 seconds
Ping with Net::Ping took 0.001262 seconds
..
Ping with backticks took 0.005421 seconds
Ping with Net::Ping took 0.00123 seconds
..
Ping with backticks took 0.00513 seconds
Ping with Net::Ping took 0.001106 seconds
..
Ping with backticks took 0.00501 seconds
Ping with Net::Ping took 0.001211 seconds
..
Ping with backticks took 0.005031 seconds
Ping with Net::Ping took 0.000958 seconds
..
Ping with backticks took 0.005107 seconds
Ping with Net::Ping took 0.001256 seconds
..
Ping with backticks took 0.005139 seconds
Ping with Net::Ping took 0.000981 seconds
..
Ping with backticks took 0.005484 seconds
Ping with Net::Ping took 0.001086 seconds
..
Ping with backticks took 0.003778 seconds
Ping with Net::Ping took 0.000643 seconds

Booyah! Knocks the socks off of what I had so far. I don't know what the overhead of using the module and/or instantiating the Net::Ping object are, so the comparison still isn't "fair" until you figure those and amortize them over the actual calls to ping(), but I am comfortable with the result being better than what I had. (And for more reasons than it just being faster)

Also, the data above are (IMO) a good representative sample, and one thing I have noticed is that the first call is always the slowest. I don't know what kind of optimization happens, but the second and later pings are (so far) always at least twice as fast as the first.

Finally, pretty convenient that 'backticks' and 'Net::Ping' have the same number of characters, eh?

I like computer programming because it's like Legos for the mind.
  • Comment on Re: I think I just found a good reason to use backticks in a void context.
  • Download Code

Replies are listed 'Best First'.
Re^2: I think I just found a good reason to use backticks in a void context.
by BrowserUk (Patriarch) on Jan 14, 2007 at 08:56 UTC
      Hi, Browser, I saw that; but I saw this in the doc: "NOTE: Unlike the other protocols, the return value does NOT determine if the remote host is alive or not since the full TCP three-way handshake may not have completed yet."

      So I guess the thing to do would be to ping the hosts outside the loop and then only loop through the hosts that respond? I guess you lose a little bit of timeliness (the whole script takes about 20 seconds to run). So it's possible that when I get to the last machine in my list, I'm working on a ping success value from ~19 seconds ago. Also, a quick benchmark of the syn vs udp protocols (similar to the one where I bm'd backticks vs Net::Ping) actually showed no advantage (some were faster, some were slower) (and that's just the outward leg!):

      Ping with Net::Ping (syn) took 0.002087 seconds
      Ping with Net::Ping (udp) took 0.000932 seconds
      ..
      Ping with Net::Ping (syn) took 0.000977 seconds
      Ping with Net::Ping (udp) took 0.001136 seconds
      ..
      Ping with Net::Ping (syn) took 0.001145 seconds
      Ping with Net::Ping (udp) took 0.001183 seconds
      ..
      Ping with Net::Ping (syn) took 0.001282 seconds
      Ping with Net::Ping (udp) took 0.001024 seconds
      ..
      Ping with Net::Ping (syn) took 0.001163 seconds
      Ping with Net::Ping (udp) took 0.001019 seconds
      ..
      Ping with Net::Ping (syn) took 0.001049 seconds
      Ping with Net::Ping (udp) took 0.000696 seconds
      ..
      Ping with Net::Ping (syn) took 0.00084 seconds
      Ping with Net::Ping (udp) took 0.000815 seconds
      ..
      Ping with Net::Ping (syn) took 0.000822 seconds
      Ping with Net::Ping (udp) took 0.000707 seconds
      ..
      Ping with Net::Ping (syn) took 0.000956 seconds
      Ping with Net::Ping (udp) took 0.000822 seconds
      ..
      Ping with Net::Ping (syn) took 0.000828 seconds
      Ping with Net::Ping (udp) took 0.000734 seconds
      ..
      Ping with Net::Ping (syn) took 0.000802 seconds
      Ping with Net::Ping (udp) took 0.000704 seconds
      ..
      Ping with Net::Ping (syn) took 0.000835 seconds
      Ping with Net::Ping (udp) took 0.000821 seconds
      ..
      Ping with Net::Ping (syn) took 0.000822 seconds
      Ping with Net::Ping (udp) took 0.000712 seconds
      ..
      Ping with Net::Ping (syn) took 0.000702 seconds
      Ping with Net::Ping (udp) took 0.000824 seconds
      ..
      Ping with Net::Ping (syn) took 0.000823 seconds
      Ping with Net::Ping (udp) took 0.000719 seconds
      ..
      Ping with Net::Ping (syn) took 0.00104 seconds
      Ping with Net::Ping (udp) took 0.000782 seconds
      ..
      Ping with Net::Ping (syn) took 0.000563 seconds
      Ping with Net::Ping (udp) took 0.000474 seconds
      

      It seems to me a better way to test the performance is something like this:(it's late so forgive me if my logic is off)

      Readonly my $udp_pinger => Net::Ping->new( 'udp', 1 ); Readonly my $syn_pinger => Net::Ping->new( 'syn', 1 ); foreach my $x ( 0 .. 5 ) { #test the syn prot with two loops my $t0 = [ gettimeofday() ]; foreach my $host (@host_list) { $syn_pinger->ping($host) || die "syn ping failed for $host"; } foreach my $host (@host_list) { $syn_pinger->ack($host) || die "syn ack failed for $host"; } my $e0 = tv_interval($t0); print "$e0 seconds to ping $NUM_HOSTS hosts with syn"; #test the udp prot with one loop $t0 = [ gettimeofday() ]; foreach my $host (@host_list) { $udp_pinger->ping($host) || die "udp ping failed for $host"; } $e0 = tv_interval($t0); print "$e0 seconds to ping $NUM_HOSTS hosts with udp"; print "---------------------------"; } ## end foreach my $x ( 0 .. 5 )
      (I didn't want to go too crazy with number of iterations, but here's a pretty representative result:
      0.015293 seconds to ping 17 hosts with syn
      0.013442 seconds to ping 17 hosts with udp
      ---------------------------
      0.013814 seconds to ping 17 hosts with syn
      0.013393 seconds to ping 17 hosts with udp
      ---------------------------
      0.01381 seconds to ping 17 hosts with syn
      0.01327 seconds to ping 17 hosts with udp
      ---------------------------
      0.014273 seconds to ping 17 hosts with syn
      0.013056 seconds to ping 17 hosts with udp
      ---------------------------
      0.014191 seconds to ping 17 hosts with syn
      0.013396 seconds to ping 17 hosts with udp
      ---------------------------
      0.016453 seconds to ping 17 hosts with syn
      0.013 seconds to ping 17 hosts with udp
      

      I suppose a better test would be just just call ack non-specifically the right number of times, and keep track of who's responded. But that seems like a lot of work to save a few milliseconds (yeah, I know--kinda late to be saying that). I'm happy going from 1.008->.008->.005->.0015 seconds per host. I think I've reached the point of diminishing returns. However, if you were checking hundreds or more hosts, I could see where that could be worth it.


      I like computer programming because it's like Legos for the mind.
        I suppose a better test would be just just call ack non-specifically the right number of times, and keep track of who's responded. But that seems like a lot of work to save a few milliseconds (yeah, I know--kinda late to be saying that). I'm happy going from 1.008->.008->.005->.0015 seconds per host. I think I've reached the point of diminishing returns. However, if you were checking hundreds or more hosts, I could see where that could be worth it.

        I absolutely agree. You've got to need the performance gain to make the extra complexity worth the effort.


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.