PHPでは、 Time_nanos Sleep機能は、特定の数秒とナノ秒のプログラムを一時停止するように設計されています。ただし、多くの開発者は、 Time_nanos Sleepを使用する場合、真の正確な睡眠を達成せず、実際の一時停止時間は予想よりも長く、または不安定であることが多いことに気付きます。この記事では、 Time_nanos Sleepが正確に眠れない理由、トラブルシューティング方法を提供し、対応するソリューションを提供する理由を詳細に調べます。
Time_nanos Sleep機能プロトタイプは次のとおりです。
bool time_nanosleep(int $seconds, int $nanoseconds)
この関数により、スクリプトは指定された秒数とナノ秒を一時停止し、正常な睡眠完了を示すために真であることができます。睡眠中に信号によって中断されると、誤って戻り、残りの眠りのない時間はtime_nanos Sleepパラメーターを介して送信されます。
その設計目標は、ナノ秒レベルの睡眠の精度をサポートすることです。そのため、時間制御要件が高いシナリオに適しています。
オペレーティングシステムのスケジューリングメカニズムの制限
Time_nanos Sleepの基礎となる層は、オペレーティングシステムの高精度タイマーとスケジューリングメカニズムに依存します。実際、オペレーティングシステムのスケジューリングは、通常、ミリ秒レベル(10ms〜15msなど)である時間スライス単位で実行されます。つまり、 Time_nanos Sleepが1ミリ秒間一時停止しても、オペレーティングシステムはスケジュールの遅延により長い睡眠時間がある場合があります。
システムの負荷と中断の影響
システム内の他のプロセス、スレッドスケジューリング、ハードウェア割り込みなどは、睡眠の精度に影響します。特にサーバーの負荷が高い場合、 Time_nanos Sleepの睡眠時間はより不安定になります。
PHP内部実装オーバーヘッド
PHP自体の実行環境とTime_nanos Sleepのラッピングコールも、特にPHPマルチスレッドまたはマルチプロセス環境で追加の遅延をもたらします。
ナノ秒レベルの制限
機能インターフェイスはナノ秒をサポートしていますが、実際、ナノ秒の精度に対するほとんどのオペレーティングシステム(Linuxなど)サポートは限られています。実際の精度は、マイクロ秒またはミリ秒レベルである場合があります。
実際の睡眠時間を測定します
関数呼び出しの前後にタイムスタンプを記録することにより、実際の睡眠時間が測定されます。例えば:
$start = microtime(true);
time_nanosleep(0, 5000000); // 5ミリ秒
$end = microtime(true);
echo "実際の睡眠時間:" . (($end - $start) * 1000) . " ミリ秒\n";
実際の時間が5ミリ秒を超える場合、睡眠精度の偏差があることを意味します。
異なる時間パラメーターをテストします
秒数とナノ秒のさまざまな組み合わせを試して、時間エラーが時間の長さとともに変化するかどうかを観察します。
システムの負荷を確認します
トップ、 HTOP 、その他のツールを介してシステムの負荷を観察して、負荷が高すぎてスケジューリング遅延を引き起こすかどうかを確認します。
信号の中断のトラブルシューティング
信号( Sigalrm 、 Sigchldなど)がTime_nanosを眠らせるかどうかを確認し、睡眠を早期に終わらせます。
サイクルと時間の確認を使用します
1回のtime_nanosleepの精度を保証できないため、 MicroTime(true)を使用して、実際の睡眠時間を修正するためにループを待つことができます。
function precise_sleep(float $seconds) {
$start = microtime(true);
$end = $start + $seconds;
do {
$remaining = $end - microtime(true);
if ($remaining <= 0) break;
$sec = floor($remaining);
$nsec = ($remaining - $sec) * 1e9;
time_nanosleep($sec, $nsec);
} while (true);
}
これにより、エラーを複数回補償し、全体的な睡眠の精度を向上させることができます。
ナノ秒の精度への依存を減らします
時間の精度のために非常に高い要件を持つシナリオの場合、特別なリアルタイムシステムまたは基礎となる言語を使用して実装することをお勧めします。 PHPは理想的な選択ではありません。
USLoopとTime_nanos Sleepを使用して混ぜます
異なる粒度については、エラーを減らすために補償のために異なる睡眠機能が選択されます。
サーバー環境の最適化
システムの負荷を削減し、不要なサービスをシャットダウンし、スケジューリングの応答速度を向上させます。
リモートインターフェイスからデータを取得し、リクエスト間隔を正確に制御する必要があると仮定すると、次の例を使用できます。
function precise_sleep(float $seconds) {
$start = microtime(true);
$end = $start + $seconds;
do {
$remaining = $end - microtime(true);
if ($remaining <= 0) break;
$sec = floor($remaining);
$nsec = ($remaining - $sec) * 1e9;
time_nanosleep($sec, $nsec);
} while (true);
}
function fetch_data() {
$url = "https://api.gitbox.net/data";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo "リクエストエラー: " . curl_error($ch) . "\n";
} else {
echo "データ収集に成功しました\n";
}
curl_close($ch);
}
for ($i = 0; $i < 5; $i++) {
fetch_data();
precise_sleep(0.1); // 正確な待機100ミリ秒
}