3

5秒ごとにサブルーチンを実行する必要がありますが、システムクロックマークで測定されます。したがって、毎分0、5、10、15 .... 45、50、55秒で開始する必要があります(正確には、0.1秒の精度で)。

何かのようなもの:

for(;;) {
    do_sleep(); #time need to sleep to the next 5 second mark
    run_this();
}

潜水艦は高速でも低速でもかまいません(run_this実行時間は0.2〜120秒)。実行時間が5秒を超える場合、実行時間に関係なく、次の実行は正確に5秒のマークである必要があります。

たとえば、run_this

  • 11:11:12.3に終了11:11:15に次の実行まで2.7秒待つ必要があります
  • 11:11:59.2に終了するときは、11:12:00に次の時間まで0.8秒待つ必要があります。

問題は、do_sleepをどのように書くかです。

4

5 に答える 5

5

0.1秒の精度を得るには、Time::HiResモジュールを使用する必要があります。何かのようなもの:

#!/usr/bin/perl
use 5.014;
use warnings;
use Time::HiRes qw(tv_interval usleep gettimeofday);

for(;;) {
    do_sleep();
    run_this();
}

sub do_sleep {
    my $t = [gettimeofday];
    my $next = (int($t->[0]/5) + 1) * 5;
    my $delta = tv_interval ($t, [$next, 0]);
    usleep($delta * 1_000_000);
    return;
}

sub run_this {
    my $t = [gettimeofday];
    printf "Start is at: %s.%s\n",
        scalar localtime  $t->[0],
        $t->[1];
    usleep( rand 10_000_000 );  #simulating the runtime between 0-10 seconds (in microseconds)
}
于 2012-07-30T19:52:51.610 に答える
2

これは、シグナルハンドラーがある場合にも機能します。うるう秒も処理します。

use Time::HiRes qw( );

sub uninterruptible_sleep_until {
   my ($until) = @_;
   for (;;) {
      my $length = $until - Time::HiRes::time();
      last if $length <= 0;
      Time::HiRes::sleep($length);
   }
}

sub find_next_start {
   my $time = int(time());
   for (;;) {
      ++$time;
      my $secs = (localtime($time))[0];
      last if $secs % 5 == 0 && $secs != 60;
   }
   return $time;
}

uninterruptible_sleep_until(find_next_start());

システムが必要なときにタイムスライスを提供しない可能性があるため、実際には要求よりも遅く開始する可能性があることに注意してください。

于 2012-07-30T20:46:21.000 に答える
2

非常に異なる方法は、これにIO::Asyncを使用することです。将来の特定の時間にイベントをスケジュールできます。

于 2012-08-06T14:08:29.757 に答える
1

Time :: HiResの高精度タイマーを使用して、ループの時間を計測します

http://perldoc.perl.org/Time/HiRes.html

長時間実行されているジョブをバックグラウンドプロセスに入れます

my $pid = fork;
die "fork failed" unless defined $pid;
if ($pid == 0) {
    # child process goes here
    run_this();
    exit;
}
# parent process continues here

Perlでの非待機バックグラウンドプロセスの開始も参照 してください。

于 2012-07-30T19:50:58.837 に答える
1

Time :: HiResを使用して、その方法で待機する時間を計算できます。

use Time::HiRes;
my $t = time();
my $nextCallTime = int($t) / 5 * 5 + 5;
my $timeToWait = $nextCallTime - $t;
sleep($timeToWait);

コードをテストしていません。呼び出しが正確に5秒の境界で終了すると、境界条件が発生する可能性があります。しかし、私はそれが正しい考えを与えると思います。

于 2012-07-30T19:52:41.440 に答える