Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

Re^2: The most precise second (timer)

by misc (Friar)
on Nov 30, 2019 at 19:53 UTC ( [id://11109489]=note: print w/replies, xml ) Need Help??


in reply to Re: The most precise second (timer)
in thread The most precise second (timer)

Reading again, and guessing...

The problem is the cumulative error,
NOT the exact timing.

So, forget my hint at the cpu tick counter.
(Which would be the most exact "timer" at the average system..)

The solution is easy, just do (Pseudocode)
$oldtimestamp = timestamp(); nanosleep(0.9seconds); while ( $oldtimestamp == timestamp() ) { nop; } spawnmyself(); dothemysterious();

This way in, say, 1 hour exactly 60*60 instances are going to be spawned.
good luck

Replies are listed 'Best First'.
Re^3: The most precise second (timer)
by tukusejssirs (Beadle) on Dec 02, 2019 at 17:20 UTC
    Anyways, you should probably keep in mind, that you're about to write a fork bomb.

    I see what you mean. Original code (not published here) had a check for that (see below) which is executed in the loop as launch(@ARGV). And if a Bash script should run periodically, we have a special Bash script to check if only one instance of a particular script is running. Although I must say, we are currently in the middle of porting of the Bash scripts to Perl.

    sub launch { return if fork; exec @_; die "Couldn't exec"; } $SIG{CHLD} = 'IGNORE';

    For Perl scripts, we use the Highlander function to eliminate the forks. This, however, could effectively kill the processes we want to run each second (n seconds), when one instance is running longer that the period.

    And generally, we need n * second intervals. Some scripts run each second, others every 5 seconds. I have created this question to find a way to run the scripts every n seconds most accurately.

    Beside of this, I guess, best way for really exact timing would be spawning the script, which now wait's within a spinlock for the current second to change.

    This is interesting to me, but I am not a Perl guru (not even a pro programmer), therefore I’d like to ask you for more info what exactly is the spawning and the spinlock (although for this I should open another question I think). Thanks. :)

    You also don't write, which platform you're on.

    We run the scripts (and Perl) on CentOS exclusively. No need for portability.

      >For Perl scripts, we use the Highlander function to eliminate the forks. This, however, could effectively kill the processes we want to run each second (n seconds), when one instance is running longer that the period.

      >And generally, we need n * second intervals. Some scripts run each second, others every 5 seconds. I have created this question to find a way to run the scripts every n seconds most accurately.


      ..you could also use the pattern of a threadpool.
      Which I'd also like to suggest; instead of forking a new processes (if you do that),
      use something like Thread::Pool

      The other point, as you experienced, when you wait for 1 second, this will never be exactly one second.

      Sometimes another process gets scheduled first, sometimes not,
      memory is sometimes in the l1 cache, sometimes l3, and so on...

      The trick for getting more accuracy is to check the timer within a loop,
      and proceed, when the second ( or whatever interval is needed) has ticked.
      The loop is called "spinloop", since it just spins, until the condition ( time ) changed.

      This is also not 100% accurate. But the interval of e.g. 1 second will stay steady. Sometimes a few microseconds earlier, sometimes later.
      Although, as others also wrote, aiming at an exact microsecond timing is futile without rtos.
      And even then you might have to go the route, I described.

      There WILL be deviation, and this will cumulate.
      (When this is the problem).

      Spawning means forking, or also spawning threads - what I'd suggest.
      Utilizing a threadpool, you can also limit the number of threads, so the fork bombing problem is gone as well.
        ..Again, in pseudocode, this would work:
        sub threadwork(){ lock(MUTEX); do{ the work; } } $t = new threadpool(42 threads); $t->do( &threadwork() ); lock(MUTEX); loop{ ct = timestamp(); sleep(0.9 seconds); # do a blocking select with timeout in perl fo +r microsecond timings loop {nop;} while (ct==timestamp()); # the spinloop #or, for a interval of 5 seconds: while ( ct+5>timestamp() ); unlock(MUTEX); }

        Hope that helps

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://11109489]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others cooling their heels in the Monastery: (7)
As of 2024-04-16 10:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found