PHP Doku:: Programm-Verzögerung in Mikrosekunden - function.usleep.html

Verlauf / Chronik / History: (1) anzeigen

Sie sind hier:
Doku-StartseitePHP-HandbuchFunktionsreferenzSonstige GrunderweiterungenMiscellaneous FunctionsSonstige Funktionenusleep

Ein Service von Reinhard Neidl - Webprogrammierung.

Sonstige Funktionen

<<unpack

Parsekit>>

usleep

(PHP 4, PHP 5)

usleepProgramm-Verzögerung in Mikrosekunden

Beschreibung

void usleep ( int $micro_seconds )

Verzögert die weitere Ausführung des Programms um die angegebene Anzahl von Mikrosekunden.

Parameter-Liste

micro_seconds

Die Anhaltezeit in Mikrosekunden. Eine Mikrosekunde ist eine millionstel Sekunde.

Rückgabewerte

Es wird kein Wert zurückgegeben.

Changelog

Version Beschreibung
5.0.0 Die Funktion arbeitet jetzt auch auf Windowssystemen.

Beispiele

Beispiel #1 usleep()-Beispiel

<?php

// Aktuelle Zeit
echo date('h:i:s') . "\n";

// Warte 2 Sekunden
usleep(2000000);

// Zurück!
echo date('h:i:s') . "\n";

?>

Das oben gezeigte Beispiel erzeugt folgende Ausgabe:

11:13:28
11:13:30

Siehe auch


17 BenutzerBeiträge:
- Beiträge aktualisieren...
adrian dot voica at gmail dot com
12.10.2009 16:15
VERY VERY IMPORTANT!!!

Under Windows systems, if you do not set the time limit of the execution of your script to 0 ("set_time_limit(0);"), the php executable will eat as much as 50% CPU power when using sleep or usleep functions.

This is an extremely annoying behavior. It took me a lot of time to figure it out. It may have something to do with the fact that the usleep and sleep are "supervised" by the time limit set by set_time_limit() which defaults to 30 seconds; --that's just my assumption. I may be wrong, I am only human ;)

It's quite simple, but the set_time_limit() function is poorly documented at this level.

<?php
 set_time_limit
(0); // Remove the time limit for command-line usage;
 
$counter = 0; // Some simple counter;
 
while ($counter < 100) { // Do nothing for 100*100 miliseconds (10 seconds);
 
$counter++;
 
usleep(100000); // Sleep for 100 miliseconds;
 
}

Good luck!
Docey
27.05.2007 23:19
WARNING!!

the snippet below by 'Marius (mm at co-operation dot de)' is NOT a usleep and it will keep the CPU at 100% running. why people keep posting that crap is a complete mystery for me.

the idea of sleep and usleep is that by letting the cpu run a few idle cycles so the other programs can have some cycles run of their own. what results in better response times and lower overall system-load. so if you have to wait for something, go to sleep for a few seconds instead of occupying the cpu while doing absolute nothing but waitting.
Marius (mm at co-operation dot de)
13.03.2007 11:15
My solution providing usleep on a windows based os:

// Helper function
function getmicrotime(){
    list($usec, $sec) = explode(' ',microtime());
    return ((float)$usec + (float)$sec);
}

// usleep alias function for windows
function msleep($micro_seconds=0) {
    $stop  = getmicrotime() + ($miliseconds / 1000);
    while (getmicrotime() <= $stop) {
        // loop
    }
    return true;
}
Mike at SevenCode dot com
11.01.2007 12:36
Dude you are SO the man for that code snippet. It worked like a charm. I just wanted to point out a couple things and offer my own improvement.

1. If you're like me, you were probably wondering why the socket had to keep being recreated on each call, and why you couldn't just create a static socket. Its because socket_select assumes you're passing in a pointer, and will alter the variable on return to reflect the actual sockets that were changed.

2. I couldn't figure out for the life of me why socket_select wasn't defined. Its because you hadn't enabled the right extension in php.ini

Ok so heres my slight improvement. The only real thing I did is use a static variable for the socket, to avoid creating a brand new socket on each call of this function. I'm not sure if socket creation will cause things to crash down the line like the other problems reported on here, but if you ask me better safe then sorry.

function Sleeper($mSec)
{
    //    For dummies like me who spent 5 minutes
    //    wondering why socket_create wasn't defined
    if(!function_exists('socket_create')){
        die("Please enable extension php_sockets.dll");
    }

    //    So the socket is only created once
    static $socket=false;
    if($socket===false){
        $socket=array(socket_create(AF_INET,SOCK_RAW,0));
    }
    $pSock=$socket;
   
    //    Calc time
    $uSex = $mSec * 1000;

    //    Do the waiting
    socket_select($read=NULL,$write=NULL,$pSock,0,$uSex);
   
    //    OCD
    return true;
}
php_manual at lk2 dot de
28.12.2006 23:16
I have no idea why nobody came up with this yet, but there is an efficient way to reproduce usleep() under windows:

<?php
function usleep_win($msec) {
  
$usec = $msec * 1000;
  
socket_select($read = NULL, $write = NULL, $sock = array(socket_create (AF_INET, SOCK_RAW, 0)), 0, $usec);
}
?>

* Doesnt busy wait
* Doesnt eat memory
* Works for millions of repetitions
* Seems to be rather efficient

It seems that the average error (on my machine) is about 5ms (it sleeps 5ms more than intended) thats probably due to code execution as well as kernel timers.

A socket without any purpose is highly unlikely to every cause an exception, so socket_select will always sleep until the timeout is hit.
Rasmus Schultz
23.08.2006 15:39
I have spent DAYS trying to create a reliable usleep()-replacement for Windows.

I have only this to offer:

As commented by someone else already, the gettimeofday() method used below is useless - PHP will use all available CPU power doing nothing.

The fsockopen() method apparently is also useless - as someone else commented, an fclose() was missing in the original post, but this apparently does not solve the problem. After calling the function about 50 or so times, fsockopen() returns immidiately, without any delay - and watching a process monitor in Windows, you can then watch the process taking up increasingly more memory, until eventually PHP aborts (or crashes) when it reaches maximum.

The win32api-method is also a no-go ... after calling the Sleep function a few hundred times (during which memory usage will also go up every time due to a memory leak somewhere), PHP will cause an exception and Windows will terminate it.

I have given up - I don't think there is any viable solution to this problem under PHP 4.

If you need this function, upgrade your project to PHP 5.

Or settle for 1-second delays with the sleep()-function.

These, unfortunately, seem to be your only options...
Patrick
26.07.2006 22:04
I want to create a daemon/Linux service. Here is an example of how to run a process that has "throttle control"

// You must set these
//
// max_execution_time = 0
// max_input_time = 0

function doProcess() {
    echo "Start"."\n";
    usleep(10000);
    echo "Stop"."\n";
    return false;
}

function manageProcess() {
    // Setup data
    $runsPerMinute = 200;
    $maxMinuteAverage = 5;
    $waitIfNotWorking = 120; // seconds

    // Conversion
    $microsPerSecond = 1000000;

    // Statistical Info
    $currentMinute = 0;
    $minute = -1;
    $countPerMinute = array();
    $sumPerMinute = array();

    // Totals
    $totalProcessTime = 0;
    $totalCounts = 0;

    while (true) {
        $timestart = microtime();
        $performedWork = doProcess();
        $timeend = microtime();

        if (!$performedWork) {
            // Statistical Info
            $currentMinute = 0;
            $minute = -1;
            $countPerMinute = array();
            $sumPerMinute = array();

            sleep($waitIfNotWorking);
        } else {

            $ts = split(" ",$timestart);
            $te = split(" ",$timeend);

            $te[0] = ($te[0] * $microsPerSecond) - ($ts[0] * $microsPerSecond);
            $te[1] = ($te[1] - $ts[1]) * $microsPerSecond;

            $processTime = $te[0] + $te[1];

            if (date("i")<>$minute) { // We are NOT in the same minute
                // Reset the new minute
                $minute = date("i");
                $currentMinute = ($currentMinute+1) % $maxMinuteAverage;

                // Remove Statistical Information from the minute we are expiring.
                if (isset($countPerMinute[$currentMinute])) {
                    $totalProcessTime = $totalProcessTime - $sumPerMinute[$currentMinute];
                    $totalCounts = $totalCounts - $countPerMinute[$currentMinute];
                }

                $countPerMinute[$currentMinute] = 0;
                $sumPerMinute[$currentMinute] = 0;
            }

            $countPerMinute[$currentMinute] = $countPerMinute[$currentMinute] + 1;
            $sumPerMinute[$currentMinute] = $sumPerMinute[$currentMinute] + $processTime;

            $totalCounts = $totalCounts + 1;
            $totalProcessTime = $totalProcessTime + $processTime;

            $averageRuntime = round($totalProcessTime / $totalCounts);

            $waitTime = (($microsPerSecond*60) / $runsPerMinute) - $averageRuntime;

            usleep($waitTime);
        }
    }

}

manageProcess();
gizmo at aoaforums dot com
3.02.2006 6:28
It should be noted that Windows machines have a resolution of either 10 mS or 15 mS (depending on the chipset implementation and HAL used) when using the Sleep() function in kernel32.dll.  This means that your average error will be either 5 or 7.5 mS.  This is not ordinarily a problem unless you really NEED to sleep for less time than the granularity provided by Windows.
gmc at serveisw3 dot net
8.07.2005 6:11
If you're using Windows then you maybe are in trouble with usleep if you really need to use it.

The Bernie's microdelay function using fsockopen does not work properly, and the fclose doesn't help much.

I don't know if network connections go strange, but I know it does not work since you've made more than 2000 - 3000 calls to it, so it's not a reliable solution in 'long life' php scripts, or these are the issues of the microdelay function in my PHP and PHP-GTK applications.

Though another solution should be found, and googling a bit I fount a WinAPI function: Sleep.

So I get with this snippet wich works fine for me, you get milliseconds precission but the more important, it works for long-run scripts and of course, it does not waste any CPU cycles.

dl('php_w32api.dll');

$GLOBALS['win32api'] =& new win32;

// USleep alternative for Windows and PHP4:
$GLOBALS['win32api']->registerfunction("long Sleep (long dwMillisecods) From kernel32.dll");

// Now you can call the function from everywhere in your script: $GLOBALS['win32api']->Sleep(milliseconds);

for ($msec = 2000; $msec > 0; $msec = $msec - 125) {
  echo "Hi. Next one in $msec msec.\n";
  $GLOBALS['win32api']->Sleep($msec);
}
t0russ at gmail dot com
3.05.2005 17:06
solution to the warning posted by Bertie:
$f=@fsockopen("tcp://localhost",$UNUSED_PORT,$errno,$errstr,$delay);
@fclose($f);
brian dot hollenbeck at gmail dot com
25.03.2005 13:28
Just a tip for the folks at home: is you use multiple rand() functions in your code, be sure to put a randomized usleep() in between the rand() codelines, or else your "random" seeds won't be so random on a fast server.

Example:

$string = rand(0, 100);
$string = rand(0, 200);

Instead:

$string = rand(0, 100);
usleep(rand(1000, 10000));
$string1 = rand(0, 100);
Bertie
28.11.2003 20:47
A word of warning about the microdelay() code posted that uses the fsockopen - if you use this is a loop that delays for small periods you will very quickly run out of sockets/socket buffer space. And then your network connections go very strange......
grail dot ink at unix dot net
29.08.2003 11:06
We have developed an alternative to usleep that should work on any platform and it doesn't eat up any CPU cycles. It's been tested on Windows 2000 w/ Apache. Other platforms should work fine.

function microdelay($delay) {
$UNUSED_PORT=31238; //make sure this port isn't being used on your server
@fsockopen("tcp://localhost",$UNUSED_PORT,$errno,$errstr,$delay);
}

It times out after a specified time in seconds. It uses a double as argument so you can specify decimal arguments.

microdelay(.5); //500ms
microdelay(.25); //250ms
microdelay(2.25); //2250ms

Our small contribution to this great language!

http://www.xencoders.com
jadd0r at mail dot com
8.04.2003 19:59
You could do neat things with this like for unix:

<?php
$y
=1000000;
for (
$x=1; $x<50; $x++) {
echo
chr(7);
usleep($y*(pow(0.9,$x)+0.2));
}
?>

then execute
`php -q script.php > /dev/console`

will result in a bombtimer (chr(7) is beep character) :]
busby at edoceo dot com
18.01.2003 1:04
Should be noted that functions that loop really fast to create a delay also consume 100% CPU while doing the loop.  Try creating a dummy loop that goes 100000 times, watch it choke your machine.  If you really need usleep() don't use windows.
dsc at c2i dot net
15.03.2002 6:55
The usleep() for Windows above doesn't take into account that the value of $stop can be lower than $start. It also contains unnecessary casts and $temp variable. Here is a better function:

function usleepWindows($usec)
{
    $start = gettimeofday();

    do
    {
        $stop = gettimeofday();
        $timePassed = 1000000 * ($stop['sec'] - $start['sec'])
            + $stop['usec'] - $start['usec'];
    }
    while ($timePassed < $usec);
}
dave at techweavers dot net
29.12.2000 4:29
To monitor a scripts CPU ussage and avoid any nasty CPU gobbling loops you can use this function (will not work with windows or safe mode) I know it works on FreeBSD:
function phpmon($max)
 {
 $cmd = `ps -Unobody -r -o%cpu`;
 $lines = explode("\n", $cmd);
 $usage = substr($lines[1], 0, strpos($lines[1], "."));
 $sleeprate = 500;
 while ($usage >= $max)
  {
  $cmd = `ps -Unobody -r -o%cpu`;
  $lines = explode("\n", $cmd);
  $usage = substr($lines[1], 0, strpos($lines[1], "."));
  usleep($sleeprate);
  }
 }

phpmon($MAX);

where $MAX is the maximum CPU you want the process to consume. e-mail me with any improvements/suggestions.

I have noticed that this consumes a lot of system CPU (at least in my limited testing) possibly from all of the system calls or the huge mathematical functions I used to test the effectiveness of the script.



PHP Powered Diese Seite bei php.net
The PHP manual text and comments are covered by the Creative Commons Attribution 3.0 License © the PHP Documentation Group - Impressum - mail("TO:Reinhard Neidl",...)