Beefy Boxes and Bandwidth Generously Provided by pair Networks
P is for Practical
 
PerlMonks  

RRD-Ping getting values on right interval

by hello_world (Acolyte)
on Nov 30, 2011 at 07:05 UTC ( [id://940785]=perlquestion: print w/replies, xml ) Need Help??

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

Hi Folks, I have a script to update the RRD databases with latency values to 5 different locations.The script forks 5 different process where each process will run the ping command to their respective location for 15 seconds and sleep for remaining 45 seconds & update the rrd databases after that with the values.

What i intend to by this is to update the RRD databases exactly at every 1 minute interval (i.ee 12:40:00 ,12:41:00,12:42:00 and so on...) The breakup is as follows:

12:40:00 - 12:40:15 (ping for 15 seconds) 12:40:15 - 12:40:59 (sleep for 45 seconds) 12:41:00 - update the rrd db

The problem i am facing is that the values dont arrive exactly at the right interval after some time..i.ee the values start to drift.

Instead of getting the value at 16:50:00 or 16:51:00 ..16:52:00 i am getting the values 3-4 seconds late i.ee 16:50:04 ..16:51:04..16:52:04
So,how do i make sure that i input the values in the db exactly at 1 minute interval ??
#!/usr/bin/perl use strict; use warnings; use Carp; use POSIX; use IO::Handle; use IPC::Open3; use Data::Dumper; sub _Forked { my $ip = shift; # croak "Couldn't fork" unless defined (my $pid = fork()); if ($pid == 0) { #CHILD while (1) { # sleep 45; my @data = `/bin/ping -w 15 -q $ip`;; my @values = ($data[4] =~ m{(\d+).\d+}g); my $time = scalar localtime(); print "$time - $ip - @values\n"; # } } # return ($pid); } sub main { my $DSname = { can => 'vfs.edu', us => 'ucla.edu', aus => 'cdu.edu.au', mal => 'um.edu.my', uk => 'imperial.ac.uk', }; # foreach my $host (keys %{$DSname}) { my $cpid = _Forked($DSname->{$host}); } # my $dpid = POSIX::waitpid(-1,WUNTRACED); } main();
The script will just print the values as of now
Output
Wed Nov 30 12:27:00 2011 - cdu.edu.au - 241 246 255 5 Wed Nov 30 12:27:00 2011 - vfs.edu - 251 254 260 3 Wed Nov 30 12:27:00 2011 - ucla.edu - 216 223 233 6 Wed Nov 30 12:27:00 2011 - um.edu.my - 112 119 124 3 Wed Nov 30 12:27:00 2011 - imperial.ac.uk - 171 178 185 6

After few hours,the values are:
Wed Nov 30 15:28:04 2011 - cdu.edu.au - 241 246 255 5 Wed Nov 30 15:28:04 2011 - vfs.edu - 251 254 260 3 Wed Nov 30 15:28:04 2011 - ucla.edu - 216 223 233 6 Wed Nov 30 15:28:04 2011 - um.edu.my - 112 119 124 3 Wed Nov 30 15:28:04 2011 - imperial.ac.uk - 171 178 185 6

Replies are listed 'Best First'.
Re: RRD-Ping getting values on right interval
by CountZero (Bishop) on Nov 30, 2011 at 09:14 UTC
    On the average you will get half a second "error" on each sleep and all other processes running will add a slight delay too. So that adds up in the end.

    Rather than rely on sleep 45 you better sleep for 40 seconds and then start polling the internal clock and launch your pings on the dot of the next minute. You will get re-synchronised that way every time and your errors will be minimal.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

      Just wondering why this half a second 'error' would happen on each sleep? Is this something normal?
        If you look at the ping report, the RT times (as printed) total 25 miliseconds; at the moment, I'm looking at RTs on the order of 90 milisecs. Either adds up to half a sec pretty fast -- just 6 (+/-) iterations in my case; 20 in yours.

        BTW, your script requires mods/workaround beyond my ken for Windoze/AS 5.12...:
        Your vendor has not defined POSIX macro WUNTRACED, used at F:\_Perl_\pl_test\940785.pl
        at my equivalent of your line 45.

        sleep has a resolution of one second. It means it can trigger anywhere in that one second and therefore on the average it will be 0.5 seconds "off" the exact mark.

        CountZero

        A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James

Re: RRD-Ping getting values on right interval
by quester (Vicar) on Nov 30, 2011 at 08:46 UTC

    Instead of "sleep 45" you can sleep until the start of the next minute with Time::HiRes:

    use Time::HiRes qw{ time sleep }; ... my $now = time; sleep 60 - ( $now - 60 * int ( $now / 60 ) );

    You might need to subtract a fraction of a second from the sleep interval if the log entries tend to end in :01 rather than :00.

Re: RRD-Ping getting values on right interval
by TJPride (Pilgrim) on Nov 30, 2011 at 08:37 UTC
    Depends on what you mean by "exactly". If it's ok to be a second or so off, it may be enough to just keep sleeping for 1 second and then checking the time to see if it's "exactly" when you need to do the next step. Just keep synchronized on system time. Beyond that, you'll have to get into milliseconds, which I'm sure someone else can supply code for (it's been too long and I don't remember the commands).
Re: RRD-Ping getting values on right interval
by pklausner (Scribe) on Nov 30, 2011 at 15:26 UTC
    Why bother with the timing in the first place? RRD is designed to handle exactly that. As the man page says: "The data is time aligned (interpolated) according to the properties of the RRD to which the data is written."

    And, from the same author, there is the excellent smokeping which does all that...

Re: RRD-Ping getting values on right interval
by decnartne (Beadle) on Nov 30, 2011 at 21:41 UTC
    snipped from some code we run for similar purposes:
    my $QUERY_INTERVAL = 60; #edit here to 60 (was 120) while( 1 ) { my $now = time; my $sleep_secs = $QUERY_INTERVAL - ( $now % $QUERY_INTERVAL ); sleep( $sleep_secs ); logmsg( "INFO", "getting counts" ); get_zcounts(); }

    decnartne ~ entranced

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://940785]
Approved by Corion
Front-paged by Corion
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (2)
As of 2024-04-25 20:25 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found