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

The objective of my code snippet is to spawn a couple of threads(two in this case) and have each thread send two cold start traps. I'm trying to build in a timing mechanism such that all the traps get sent within a specific amount of time (one second in this case). When you run the code you'll see my question. It seems that the first iteration of the second thread always fails due to a negative time calculation. I've tried locking the variables down until they go out of scope so they aren't stepping on each other, but this doesn't seem to work.

Any help or suggestions would be greatly appreciated.
Thanks!

#!C:/perl/bin/perl.exe use warnings; use strict; use threads; use threads::shared; use Net::SNMP; use Time::HiRes qw(usleep gettimeofday tv_interval); my $t0s : shared = 1; my $t1s : shared = 1; my $t0m : shared = 1; my $t1m : shared = 1; my $rest : shared = 1; my $elapsedtime : shared = 1; my $tmp : shared = 1; my $gen = 0; my $src = '18.42.246.82'; my $dest = '18.42.248.124'; my $iterations = 2; my $sec = 1000000; my $sleep = ( $sec / ($iterations * 2)); my $t0 = [gettimeofday]; my ($t0secs, $t0micro) = gettimeofday; my $thr = threads->create(\&sendTrap, $gen, $src, $dest, $iterations); my $thr2 = threads->create(\&sendTrap, $gen, $src, $dest, $iterations) +; $thr->join; $thr2->join; my $t1 = [gettimeofday]; my $elapsed = tv_interval $t0, $t1; print "\nTotal Elapsed Time: $elapsed\n"; # Should be close to one sec +cond sub sendTrap { my ($gen, $src, $dest, $i) = @_; for(1..$i) { ($t0s, $t0m) = gettimeofday; lock($t0m); my $oid = '1.3.6.1.4'; my @trapvars = (); my ($session, $error) = Net::SNMP->session( -hostname => $dest, -community => 'public', -port => 162 ); if (!defined($session)) { printf("ERROR: %s.\n", $error); exit 1; } my $result = $session->trap( -enterprise => $oid, -agentaddr => $src, -generictrap => $gen, -specifictrap => '0', -varbindlist => \@trapvars ); if (!defined($result)) { printf("ERROR: %s.\n", $session->error); $session->close; exit 1; } $session->close; ($t1s, $t1m) = gettimeofday; lock($t1m); lock($elapsedtime); $elapsedtime = $t1m - $t0m; if ($elapsedtime =~ /\-/) { lock($tmp); $tmp = $elapsed; $tmp =~ s/\-//; $elapsedtime = 1000000 - $tmp; } print "\n\nStart Sleep: $sleep\n"; print "Elapsed Time: $elapsedtime\n"; lock($rest); $rest = ($sleep - $elapsedtime); print "Net Sleep: $rest\n"; usleep $rest; } }

Replies are listed 'Best First'.
Re: sleep and timing?
by BrowserUk (Patriarch) on Nov 23, 2005 at 14:48 UTC

    Why, if you want two actions to happen within a specified time of each other, are you putting them in threads? Especially as the actions are SNMP traps, which are UDP messages for which there is no reply, so no IO wait for the second event to overlap.

    You are trying to arrange for two threads to synchronise, which whilst possible if your running on a multiprocessor system, is a very hard (and pointless) exercise.

    Even if you are running on multi-processor hardware, unless it is multi-homed also, your carefully synchronised traps will be serialised at the network stack.

    And if ir is multi-homed, unless the destination hardware, and every node in between is also multi-processor and multi-homed, one of them will serialise the traps as they pass through.

    Finally, if any other traffic is using any of the cable runs or any of the intervening nodes, it will almost certainly delay one trap relative to the other. Even if you succeed in causing the traps to be passed onto the network with specific timing, there is no guarentee, and absolutely no chance(*) that they will arrive at their destination(s) with that same timing.

    Two dual-processor, dual-homed systems connected back to back in complete isolation might maintain the timing, but even that is unlikely.

    Finally, with UDP messages, if you just sent them serially from a single thread, it is almost unthinkable that they would not be transmitted within one second of each other. Even if your outbound connection was via 1200 baud modem, unless your data packets are pretty big, you could expect to transmit many more than two UDP messages serially, from a single thread within 1 second.

    There just doesn't seem to be any good reason for doing what you are trying to do. Please correct me if I am not seeing the whole picture?


    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
      My objective (crazy or not) is to send N number of traps in a specific amount of time. I'm trying to do some performance testing so I'm not concerned about the destination or the arrival time at the other end.

        Then rather than trying to send for an exact time period and count how many you succeeded in transmitting, do it the other way around. Transmit a set number of traps and time how long it took. Set the number to send relatively high and divide that number by the number of seconds taken to arrive at an average throughput per second.

        This is a simulation.

        Although each "trap" delays at least 10 ms and an average of 30 millseconds, threading allows those delays to overlap, so the ultimate cost per trap is under 4 ms.

        HTH


        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re: sleep and timing?
by zentara (Cardinal) on Nov 23, 2005 at 14:06 UTC
    Just brainstorming..... I'm not running windows, but I don't see how you can expect timing to be reliable, when you are creating an object, and connecting to the internet in the threads. Can you come up with an example that dosn't use Net::SNMP? Maybe you could create the threads first, wait for them both to return a "ready" signal through a shared variable, then "fire the starting pistol" and determine timings.

    But I may not really understand your question. :-)


    I'm not really a human, but I play one on earth. flash japh