Skip to content

Commit

Permalink
Improved accuracy
Browse files Browse the repository at this point in the history
  • Loading branch information
shimonhaga committed Jul 6, 2022
1 parent b82da5a commit 71657f3
Show file tree
Hide file tree
Showing 5 changed files with 72 additions and 59 deletions.
22 changes: 14 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Sleep utilities
sleep / usleep / time_nanosleep を拡張し、直感的にわかりやすくしたもの。

## Support
PHP7.0 以上。

将来的には 7.3 以上にする予定 (hrtime を使いたい)。

## Install
利用するプロジェクトの `composer.json` に以下を追加する。
```composer.json
Expand All @@ -27,36 +32,37 @@ composer update shimoning/sleep-utilities
**** を指定して sleep する。

```php
Sleep::seconds(5);
Sleep::seconds(5.5);
```

### Sleep::milliSeconds
**ミリ秒** を指定して sleep する。

```php
Sleep::milliSeconds(20);
Sleep::milliSeconds(20.30);
```

### Sleep::microSeconds
**マイクロ秒** を指定して sleep する。

```php
Sleep::microSeconds(300);
Sleep::microSeconds(300.500);
```

### Sleep::nanoSeconds
**ナノ数** を指定して sleep する。
**ナノ秒** を指定して sleep する。

```php
Sleep::nanoSeconds(120);
```

### Sleep::decimalSeconds
**小数を含む秒** を指定して sleep する。
整数でも利用可能。
### Sleep::usleep
**マイクロ秒** を指定して sleep する。
PHP 標準の usleep の精度を若干向上し、 int だけでなく float も扱えるようにした。
seconds, milliSeconds, microSeconds の基盤関数。

```php
Sleep::decimalSeconds(3.25);
Sleep::usleep(300);
```

-----
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"description": "Sleep utilities",
"minimum-stability": "stable",
"type": "library",
"version": "0.1.1",
"version": "0.2.0",
"license": "MIT",
"authors": [
{
Expand Down
2 changes: 1 addition & 1 deletion psysh.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

echo __NAMESPACE__ . " shell\n";
echo "-----\nexample:\n";
echo "echo microtime(); echo \"\\n\"; Sleep::seconds(2); echo microtime();\n";
echo "echo microtime(true); echo \"\\n\"; Sleep::seconds(2); echo microtime(true);\n";
echo "-----\n\n";

$sh = new \Psy\Shell();
Expand Down
87 changes: 41 additions & 46 deletions src/Sleep.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,96 +5,91 @@
/**
* sleep/usleep の発展系
*
* TODO: PHP7.3 以上のサポートにして microtime() から hrtime() に変更し精度を上げる
* 現状だとミリ秒までの精度しか出ない
*
* @author Shimon Haga <[email protected]>
*/
class Sleep
{
const KILO = 1000;
const MEGA = 1000000;
const GIGA = 1000000000;
const KILO = 1e3;
const MEGA = 1e6;
const GIGA = 1e9;

/**
* 秒単位で処理を遅延させる (PHP 標準の sleep とほぼ同じ)
*
* @param int $t
* @return int
* @param int|float $t
* @return void
*/
public static function seconds(int $t)
public static function seconds($t)
{
return \sleep(Tool::sanitize($t));
$baseMicroSeconds = \microtime(true);
$seconds = Tool::positiveFloat($t);
self::usleep($seconds * self::MEGA, $baseMicroSeconds);
}

/**
* ミリ秒単位で処理を遅延させる
*
* @param int $t
* @param int|float $t
* @return void
*/
public static function milliSeconds(int $t)
public static function milliSeconds($t)
{
$time = Tool::sanitize($t);
if ($time > self::KILO) {
// システムによっては 1秒以上 をサポートしないことがある
self::seconds(\floor($time / self::KILO));
$time %= self::KILO;
}
return \usleep($time * self::KILO);
$baseMicroSeconds = \microtime(true);
$milliSeconds = Tool::positiveFloat($t);
self::usleep($milliSeconds * self::KILO, $baseMicroSeconds);
}

/**
* マイクロ秒単位で処理を遅延させる
*
* @param int $t
* @param int|float $t
* @return void
*/
public static function microSeconds(int $t)
public static function microSeconds($t)
{
$time = Tool::sanitize($t);
if ($time > self::MEGA) {
// システムによっては 1秒以上 をサポートしないことがある
self::seconds(\floor($time / self::MEGA));
$time %= self::MEGA;
}
return \usleep($time);
$baseMicroSeconds = \microtime(true);
$microSeconds = Tool::positiveFloat($t);
self::usleep($microSeconds, $baseMicroSeconds);
}

/**
* ナノ秒単位で処理を遅延させる
*
* @param int $t
* @param int|float $t
* @return array|bool
*/
public static function nanoSeconds(int $t)
public static function nanoSeconds($t)
{
$time = Tool::sanitize($t);
$time = Tool::positiveFloat($t);
$seconds = \floor($time / self::GIGA);
$nanoseconds = $time % self::GIGA;
return \time_nanosleep($seconds, $nanoseconds);
$nanoSeconds = $time % self::GIGA;
return \time_nanosleep($seconds, $nanoSeconds);
}

/**
* 小数が含まれる秒単位で処理を遅延させる
* usleep 互換
* 精度を少し上げ、小数も引き受けるようにした
*
* @param int|float $t
* @param float|int $microSeconds
* @param float|null $baseTime
* @return void
*/
public static function decimalSeconds($t)
public static function usleep($microSeconds, float $baseMicroSeconds = null)
{
if (! \is_numeric($t) || $t < 0) {
// 数値じゃない、もしくは負の時は何もしない
return;
}
$targetSeconds = ($baseMicroSeconds ?: \microtime(true)) + $microSeconds / self::MEGA;

if (\is_int($t)) {
// 整数の場合
self::seconds($t);
return;
if ($microSeconds > self::MEGA) {
// システムによっては 1秒以上 をサポートしないことがある
\sleep(\floor($microSeconds / self::MEGA));
}

// float の場合
$time = (float)$t;
$seconds = \floor($time);
$nanoseconds = \floor(($time - $seconds) * self::GIGA);
\time_nanosleep($seconds, $nanoseconds);
while (($diffSeconds = $targetSeconds - \microtime(true)) > 0) {
if ($diffSeconds < 0.001) {
\usleep($diffSeconds * 5e5);
}
}
}
}
18 changes: 15 additions & 3 deletions src/Tool.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ class Tool
*/
public static function random(int $min, int $max): int
{
$min = self::sanitize($min);
$max = self::sanitize($max);
$min = self::positiveInteger($min);
$max = self::positiveInteger($max);
return \function_exists('random_int')
? \random_int($min, $max) // php >= 7.0
: \mt_rand($min, $max);
Expand All @@ -31,9 +31,21 @@ public static function random(int $min, int $max): int
* @param mixed $value
* @return int
*/
public static function sanitize($value)
public static function positiveInteger($value)
{
if ($value < 0) { $value = 0; }
return (int)$value;
}

/**
* 値を1以上の非負の小数にする
*
* @param mixed $value
* @return float
*/
public static function positiveFloat($value)
{
if ($value < 0) { $value = 0; }
return (float)$value;
}
}

0 comments on commit 71657f3

Please sign in to comment.