名前¶
Time::HiRes - 高精度のalarm, sleep, gettimeofday, インターバル・タイマー
概要¶
use Time::HiRes qw( usleep ualarm gettimeofday tv_interval );
usleep ($microseconds);
ualarm ($microseconds);
ualarm ($microseconds, $interval_microseconds);
$t0 = [gettimeofday];
($seconds, $microseconds) = gettimeofday;
$elapsed = tv_interval ( $t0, [$seconds, $microseconds]);
$elapsed = tv_interval ( $t0, [gettimeofday]);
$elapsed = tv_interval ( $t0 );
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep ($floating_seconds);
alarm ($floating_seconds);
alarm ($floating_seconds, $floating_interval);
use Time::HiRes qw( setitimer getitimer
ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF ITIMER_REALPROF );
setitimer ($which, $floating_seconds, $floating_interval );
getitimer ($which);
説明¶
Time::HiRes
モジュールはusleep
,ualarm
, gettimeofday
, そして setitimer
/getitimer
システムコーム、言い換えれば高精度の時刻と タイマーへのへのPerlインターフェースを実装します。 使い方については下記の"使用例"セクションとテスト・スクリプトをご覧ください; 基になっているnanosleep
あるいは usleep
, ualarm
, gettimeofday
, そして setitimer
/getitimer
については、あなたのシステムのドキュメントを ご覧ください。
あなたのシステムにgettimeofday()
やそのエミュレーションがなければ、 gettimeofday()
や引数1つの形でのtv_interval()
は使えません。 あなたのシステムにnanosleep()
, usleep()
, そして select()
,の全てが なければ、Time::HiRes::usleep()
や Time::HiRes::sleep()
は使えません。 あなたのシステムにualarm()
and setitimer()
の両方がなければ Time::HiRes::ualarm()
や Time::HiRes::alarm()
が使えません。
use
ステートメントのなかで実装されていない関数をインポートしようとすれば、 コンパイル時に失敗します。
あなたの1秒以下のsleepがusleep()
ではなくnanosleep()
で実装されていれば、 nanosleep()
はシグナルを使わないので、1秒以下のsleepとシグナルを混在させる ことができます。しかしこれは移植性を欠きます。そしてまず最初にnanosleepを 持っているのか、&Time::HiRes::d_nanosleep
の値がtrueであるかチェック しなければなりません。それから特有なことがないか慎重にnanosleep()
C API ドキュメントを読まなければなりません。(nanosleep()
を呼び出す別の インターフェースはありません;十分に小さな値で単にTime::HiRes::sleep()
や Time::HiRes::usleep()
を呼ぶだけです。)
sleepとシグナルを混在させるためにnanosleep
を使わなければ、 Perlがナノ秒の正確さを要求される仕事のために使うべきツールであるか という疑問があります。
このモジュールから以下の関数をインポートすることができます。 デフォルトでエクスポートされる関数はありません。
- gettimeofday ()
-
配列コンテキストではエポックからの秒とマイクロ秒2つの要素の配列を返します。 スカラー・コンテキストでは、
Time::HiRes::time()
のように秒を 浮動小数点数で返します(下記参照)。 - usleep ( $useconds )
-
指定されたマイクロ秒数、sleepします。実際にsleepしたマイクロ秒数を 返します。
usleep
システム・コールとは違い、1秒以上sleepすることができます。 下記のTime::HiRes::sleep()
もご覧ください。 - ualarm ( $useconds [, $interval_useconds ] )
-
ualarm
コールを発行します;$interval_useconds
はオプションで、 指定されなければ0になり、その結果はalarm
のような動きをします。 - tv_interval
-
tv_interval ( $ref_to_gettimeofday [, $ref_to_later_gettimeofday] )
2つの時刻の時間を浮動小数点の秒数を返します。2つの時刻は
gettimeofday()
で 返されたものでなければなりません。2番目の引数が省略されると、 現在の時刻が使われます。 - time ()
-
浮動小数点でエポックからの秒数を返します。この関数はインポートする ことができます、その結果、Perlのコアで提供される差し込み式に
time
を 置き換えることになります;下記の"使用例"をご覧ください。注意 1: この高精度のtimeは、あなたのプラットホームがコアの
time()
を 得るために、より高精度の時刻を切り上げたり、切り捨てたり、一番近い秒に するのいずれかによって、コアのtime()
よりも多かったり、少なかったり することがあります。しかし当然、その差は0.5秒を越えることはありえません。注意 2: 2001年9月9日 日曜日 GMTの午前 1:46:40より、 エポックからの
time()
秒は、1_000_000_000を超えています。 Perlでのデフォルトの浮動小数点のフォーマットとエポックからの秒数が あいまって明らかなバグを作り出します:Time::HiRes::time()
の値を 出力すると、保証された6桁(マイクロ秒)ではなく5桁の数字しか得ることが できません。ご心配なく。マイクロ秒は存在します(もちろんあなたの プラットホームが、そのような粒度をサポートしているものと想定しています)。 何が起きているかといえば、Perlの浮動小数点のデフォルトのフォーマットでは 15桁の数字しか出力しません。この場合、小数点の前に0桁の数字があり、 その後ろに5桁あります。マイクロ秒を見るためには"%.6f"
でprintf
/sprintf
の どちらかを使うか、リスト・コンテキストでgettimeofday()
を使うことができます。 この場合には、秒とマイクロ秒の2つを別の値として与えてくれます。 - sleep ( $floating_seconds )
-
指定された秒数、sleepします。実際にsleepした秒数を(浮動小数点の値で) 返します。この関数はインポートする ことができます、その結果、Perlのコアで提供される差し込み式に
sleep
を 置き換えることになります;下記の"使用例"をご覧ください。 - alarm ( $floating_seconds [, $interval_floating_seconds ] )
-
指定され秒数後、
SIGALRM
シグナルが送られます。ualarm()
を使って 実装されています。$interval_floating_seconds
引数は オプションで指定されないと0になります。その結果、alarm()
のような 動きになります。この関数はインポートする ことができます。その結果、Perlのコアで提供される差し込み式にalarm
を 置き換えることになります;下記の"使用例"をご覧ください。注意 1: オペレーティング・システムとPerlのリリースの 組み合わせによっては
SIGALRM
が中断させるのではなく、select()
を 再開始させることもあります。これはalarm()
の後にselect()
を すると、alarm()
に指定した時間通りにではなく、alarm()
とselect()
に指定された時間の合計が掛かるかも しれないことを意味します。 - setitimer ( $which, $floating_seconds [, $interval_floating_seconds ] )
-
インターバル・タイマーを開始させます;一定の時間後、シグナルが届き、 ある間隔でシグナルが届き続けるかもしれません。タイマーを止めるには、
$floating_seconds
を0にしてください。$interval_floating_seconds
に 0が指定されると(あるいは指定されないと)、タイマーは次にシグナルが届いた 後に止められます。インターバル・タイマーを使うことは
alarm()
,sleep()
、usleep()
に よって邪魔されるかもしれません。標準的には「相互作用は特定されていません」 つまりは何が起きるかわかりません:動くかもしれませんし、そうでないかもしれません。スカラー・コンテキストではタイマーでの残り時間が返されます。
リスト・コンテキストでは、残り時間とインターバルが返されます。
通常3つあるいは4つのインターバル・タイマーが利用可能です:
$which
はITIMER_REAL
,ITIMER_VIRTUAL
,ITIMER_PROF
, あるいはITIMER_REALPROF
に することができます。どれが利用できるかは以下のことに依存します:本当のUNIX プラットホームは通常最初の3つを持っています。しかし(例えば)Win32とCygwinはITIMER_REAL
しかもっていません。SolarisはITIMER_REALPROF
を持っているようです (これはマルチスレッドなプログラムをプロファイルするために使われます)。ITIMER_REAL
は結果としてalarm()
のような動きにします。 時間は実時間;つまり壁時計の時間で計られます。 タイマーが時間切れになるとSIGALRM
が送られます。ITIMER_VIRTUAL
は(プロセス)仮想の時間で時間を計ります; つまりプロセスが実行しているときだけです。マルチプロセッサ/ユーザ/CPU の システムではこれは実時間あるいは壁時計の時間とは多かったり、少なかったりします。 (この時間はユーザー時間(user time)とも呼ばれます。タイマーが 時間切れになるとSIGVTALRM
が送られます。ITIMER_PROF
はプロセス仮想時間、あるいは(I/Oのように)プロセスの半分で オペレーティング・システムが走っている時間を計ります。 (この時間はシステム時間(system time)とも呼ばれます。) タイマーが時間切れになると、SIGPROF
が送られます。SIGPROF
は システム・コールを中断させることができます。マルチスレッドなプログラムでのインターバル・タイマーの意味は システムによります。そしてシステムによっては、さらに他の インターバル・タイマーをサポートしているかもしれません。 あなたの
setitimer()
のドキュメントをご覧ください。 - getitimer ( $which )
-
$which
で指定されたインターバル・タイマーでの残り時間を返します。スカラー・コンテキストでは、残り時間が返されます。
リスト・コンテキストでは残り時間とインターバルの両方が返されます。 インターバルは常に、
setitimer()
を使ったときに入れたものです。
使用例¶
use Time::HiRes qw(usleep ualarm gettimeofday tv_interval);
$microseconds = 750_000;
usleep $microseconds;
# 2.5秒後、その後は0.1行ごとにシグナル・アラーム
ualarm 2_500_000, 100_000;
# エポックからの秒とマイクロ秒を取得
($s, $usec) = gettimeofday;
# 経過時間の計測
# (2つのgettimeofdayの戻り値を引くことによっても可能です)
$t0 = [gettimeofday];
# ここで何か処理の固まりを実行
$t1 = [gettimeofday];
# さらに処理の固まりを実行
$t0_t1 = tv_interval $t0, $t1;
$elapsed = tv_interval ($t0, [gettimeofday]);
$elapsed = tv_interval ($t0); # equivalent code
#
# time, alarm そして sleepを浮動小数点での秒がわかる
# もので置き換え
#
use Time::HiRes;
$now_fractions = Time::HiRes::time;
Time::HiRes::sleep (2.5);
Time::HiRes::alarm (10.6666666);
use Time::HiRes qw ( time alarm sleep );
$now_fractions = time;
sleep (2.5);
alarm (10.6666666);
# プロセス仮想時間で最初に10秒、その後は2.5秒ごとに
# やってくるインターバルタイマーを装備する
use Time::HiRes qw ( setitimer ITIMER_VIRTUAL time );
$SIG{VTALRM} = sub { print time, "\n" };
setitimer(ITIMER_VIRTUAL, 10, 2.5);
C API¶
拡張を書く人には上記のperl APIに加えて、C APIを利用することが 利用できます。以下のCの関数がmodglobalハッシュで利用することが できます:
関数名 Cプロトタイプ
--------------- ----------------------
Time::NVtime double (*)()
Time::U2time void (*)(UV ret[2])
関数は両方とも(gettimeofday
のような)同じ情報を返します。 しかしその表現が違います。NVtime
と U2time
という名前は主に オペレーティング・システムに依存していないために選択されています。 (VMSのようにいくつかのプラットホームではそのエミュレーションを 備えていますが、gettimeofday
はUnix中心的です。)
CからNVtime
を使ったときの例を以下に示します:
double (*myNVtime)();
SV **svp = hv_fetch(PL_modglobal, "Time::NVtime", 12, 0);
if (!svp) croak("Time::HiRes is required");
if (!SvIOK(*svp)) croak("Time::NVtime isn't a function pointer");
myNVtime = INT2PTR(double(*)(), SvIV(*svp));
printf("The current time is: %f\n", (*myNVtime)());
DIAGNOSTICS(診断)¶
negative time not invented yet¶
(=マイナスの時刻はまだ発明されていません) 引数としてマイナスの時刻を使おうとしました。
internal error: useconds < 0 (unsigned ... signed ...)¶
何かひどい障害がおきました -- マイナスになるはずのないマイクロ秒数は マイナスになってしまいました。コンパイラが壊れているのかも?
注意¶
コアのtime()
が切り捨てるのではなく、四捨五入するかもしれないことに 注意してください。これはコアのtime()
がgettimeofday()
や Time::HiRes::time()
よりも1秒遅い時間を報告するかもしれないという ことを意味します。
作者¶
D. Wegscheid <wegscd@whirlpool.com> R. Schertler <roderick@argon.org> J. Hietaniemi <jhi@iki.fi> G. Aas <gisle@aas.no>
コピーライト & ライセンス¶
Copyright (c) 1996-2002 Douglas E. Wegscheid. All rights reserved.
Copyright (c) 2002,2003,2004 Jarkko Hietaniemi. All rights reserved.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
翻訳者¶
川合孝典(GCD00051@nifty.ne.jp)