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

I want to start an application at a specific time and stop it at another specific time. What I have done so far that is:
use strict; use Time::Hires qw (usleep); my $start = foo my $stop = bar while () { my $now = ParseDate("now"); if ( Date_Cmp( $start, $now ) == 0 ) { start_application; } if ( Date_Cmp( $stop, $now ) <= 0 ) { stop_application; last; } usleep(800000); }
The script must work for Linux and Windows. Start and Stop times have to be accurate. This snippet works for me.
I am just thinking of an alternative method which uses minimum cpu and memory.
I read that sleep can put the processor under heavy load. usleep works quite ok but there is always more than one way to do it.

Replies are listed 'Best First'.
Re: Alternatives for "sleepy" while loop
by moritz (Cardinal) on Mar 17, 2008 at 15:18 UTC
    Since stop time is always larger than start time (it would run forever otherwise) you could do the following:
    1. Calculate time difference between $start and now
    2. usleep() that difference
    3. launch the process
    4. calculate the difference between $stop and now
    5. usleep() that difference
    6. stop the application

    That way you only need two usleep() calls.

      Just one caveat when using sleep and usleep... you generally will want to use code like this:
      my $time_to_sleep = ... # while ($time_to_sleep > 0) { $time_to_sleep = Time::HiRes::usleep($time_to_sleep); }
      The use of signals in your program can cause sleep and usleep to return before the amount of time specified. Here's an example:
      use Time::HiRes; $SIG{ALRM} = sub { warn "alarm went off" }; alarm(5); my $t = Time::HiRes::usleep(10_000_000); # 10 seconds print "done, t = $t\n";
      The 'done' message is printed approx. 5 seconds into program execution.

      Yet another implementation possibility is to use the OS's interval timers like this:

      use Time::HiRes qw(setitimer ITIMER_VIRTUAL); my $state; $SIG{ALRM} = sub { if ($state == 0) { warn "starting application"; # start application here $state = 1; my $wait_time = 10; # compute time to wait here setitimer(ITIMER_REAL, $wait_time, 0); } else { warn "stopping application"; # stop application here $state = 2; setitimer(ITIMER_REAL, 0, 0); # disable interval timer } }; # wait for 5 seconds before starting app $state = 0; setitimer(ITIMER_REAL, 5, 0); while ($state != 2) { # do other stuff... }
      This is more of a multi-threaded approach which allows you to perform other tasks during the wait periods.
Re: Alternatives for "sleepy" while loop
by chromatic (Archbishop) on Mar 17, 2008 at 17:30 UTC
    I read that sleep can put the processor under heavy load.

    Where did you read that? It's not the case for any operating system with which I'm familiar.

Re: Alternatives for "sleepy" while loop
by DACONTI (Scribe) on Mar 18, 2008 at 03:13 UTC
    Hi walto
    if you want to minimize os ressource consumption
    I think you are a bit on the wrong path
    What are you doing here in fact is a job scheding work.
    So if I would be in you I would just use system's provided ressources i.e. someting like 'at'
    I browsed for you at CPAN and found out:
    Schedule::At
    which seems to be os independent. I never tried it, but I would start from this approach.
    Perhaps it is precise enough for your purposes.
    Of course then you would need to store/retrieve back any runtime info.
    Because of this you would maybe pay a bit of performance on one side, on the other side you would however even free system's memory.
    Best Regs,
    Davide.
      Thanks for your answers.
      I already changed my script to moritz suggestion. This is a much better approach and allows a more exact control for timing.

      A script that can handle threads is the way it should go, but for this I must rewrite some other parts of the script regarding killing the running processes etc...

      I do not know where I read about the memory and cpu consumption of sleep. Actually I googled around and could not verify my statement. So probably this is not true (Although I remember one of my scripts using quite a lot cpu or mem while sleeping, but this can also have other reasons).Anyway the alternatives are great and improved my script very much.

      I searched CPAN before writing my script and could not find anything suitable. Schedule::At seems to do what I need. I will give it a second thought.