Performance of while(true) loop

Performance of while(true) loop

am 10.09.2009 04:32:27 von APseudoUtopia

Hey list,

I have a php cli script that listens on a UDP socket and, when data is
sent to the socket, the script inserts it into a database. I'm using
the real BSD socket functions, not fsock.

The script runs socket_create(), then socket_bind(). Then it starts a
while(TRUE) loop. Within the loop, it runs socket_recvfrom(). I have
it running 24/7 inside a screen window.

I'm curious as to the cpu/memory/etc usage of a while(true) loop. The
`top` command shows that the process is in the sbwait state (the OS is
FreeBSD). I'm contemplating adding a usleep or even a sleep inside to
loop. Would this be beneficial? I'm not too sure of how the internals
of PHP work in terms of loops and such.

Thanks.

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Re: Performance of while(true) loop

am 10.09.2009 04:39:32 von Eddie Drapkin

On Wed, Sep 9, 2009 at 10:32 PM, APseudoUtopia wrote:
> Hey list,
>
> I have a php cli script that listens on a UDP socket and, when data is
> sent to the socket, the script inserts it into a database. I'm using
> the real BSD socket functions, not fsock.
>
> The script runs socket_create(), then socket_bind(). Then it starts a
> while(TRUE) loop. Within the loop, it runs socket_recvfrom(). I have
> it running 24/7 inside a screen window.
>
> I'm curious as to the cpu/memory/etc usage of a while(true) loop. The
> `top` command shows that the process is in the sbwait state (the OS is
> FreeBSD). I'm contemplating adding a usleep or even a sleep inside to
> loop. Would this be beneficial? I'm not too sure of how the internals
> of PHP work in terms of loops and such.
>
> Thanks.
>
> --
> PHP General Mailing List (http://www.php.net/)
> To unsubscribe, visit: http://www.php.net/unsub.php
>
>

Is your socket blocking? If so, what's the timeout?

while(true) {

//wait for socket timeout

}

is the same as:

while(true) {

//read nothing from socket and sleep

}

Without the usleep(), the loop is going to loop as fast as your CPU
will let it - meaning 100% CPU usage, all the time, at least in linux,
although I'm pretty sure BSD would behave the same.

As far as I'm aware, sockets in PHP behave almost identically to the
way that they behave in C. I had an asynchronous TCP server written
with the socket_* functions and noticed that the while(true) loop used
100% of the CPU because of the nonblocking sockets in use, but a
usleep() solved that quite easily. Using blocking sockets with
socket_select and a sane timeout relieved the high CPU usage as well.

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Re: Performance of while(true) loop

am 10.09.2009 04:53:06 von APseudoUtopia

On Wed, Sep 9, 2009 at 10:39 PM, Eddie Drapkin wrote:
> On Wed, Sep 9, 2009 at 10:32 PM, APseudoUtopia =
wrote:
>> Hey list,
>>
>> I have a php cli script that listens on a UDP socket and, when data is
>> sent to the socket, the script inserts it into a database. I'm using
>> the real BSD socket functions, not fsock.
>>
>> The script runs socket_create(), then socket_bind(). Then it starts a
>> while(TRUE) loop. Within the loop, it runs socket_recvfrom(). I have
>> it running 24/7 inside a screen window.
>>
>> I'm curious as to the cpu/memory/etc usage of a while(true) loop. The
>> `top` command shows that the process is in the sbwait state (the OS is
>> FreeBSD). I'm contemplating adding a usleep or even a sleep inside to
>> loop. Would this be beneficial? I'm not too sure of how the internals
>> of PHP work in terms of loops and such.
>>
>> Thanks.
>>
>> --
>> PHP General Mailing List (http://www.php.net/)
>> To unsubscribe, visit: http://www.php.net/unsub.php
>>
>>
>
> Is your socket blocking?  If so, what's the timeout?
>
> while(true) {
>
> //wait for socket timeout
>
> }
>
> is the same as:
>
> while(true) {
>
> //read nothing from socket and sleep
>
> }
>
> Without the usleep(), the loop is going to loop as fast as your CPU
> will let it - meaning 100% CPU usage, all the time, at least in linux,
> although I'm pretty sure BSD would behave the same.
>
> As far as I'm aware, sockets in PHP behave almost identically to the
> way that they behave in C.  I had an asynchronous TCP server written
> with the socket_* functions and noticed that the while(true) loop used
> 100% of the CPU because of the nonblocking sockets in use, but a
> usleep() solved that quite easily.  Using blocking sockets with
> socket_select and a sane timeout relieved the high CPU usage as well.
>

I believe it is blocking. Here's my socket_recvfrom:
$Recv =3D socket_recvfrom($Socket, $Data, 512, MSG_WAITALL, $Name, $Port);

So I think the the MSG_WAITALL is causing it to block until incoming
data connection is closed (it never reaches the 512 byte mark before
it echos the data). Here's the full script, minus the debugging/error
catching stuff:

$Socket =3D socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$Bind =3D socket_bind($Socket, '127.0.0.1', 1223);
while(TRUE){
$Recv =3D socket_recvfrom($Socket, $Data, 512, MSG_WAITALL, $Name, $Port);
print_r($Data);
}

As soon as the message is sent on the socket, it displays it. There's
no delay until it builds up 512 bytes or anything. Also, I was playing
around with ps and it looks like it's using 0% CPU, so I suppose it
must be blocking.

In the case that it is blocking, would it still be wise to throw a
usleep in there just to be sure?

Thanks.

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Re: Performance of while(true) loop

am 10.09.2009 05:25:24 von Eddie Drapkin

On Wed, Sep 9, 2009 at 10:53 PM, APseudoUtopia wr=
ote:
> On Wed, Sep 9, 2009 at 10:39 PM, Eddie Drapkin wrote:
>> On Wed, Sep 9, 2009 at 10:32 PM, APseudoUtopia =
wrote:
>>> Hey list,
>>>
>>> I have a php cli script that listens on a UDP socket and, when data is
>>> sent to the socket, the script inserts it into a database. I'm using
>>> the real BSD socket functions, not fsock.
>>>
>>> The script runs socket_create(), then socket_bind(). Then it starts a
>>> while(TRUE) loop. Within the loop, it runs socket_recvfrom(). I have
>>> it running 24/7 inside a screen window.
>>>
>>> I'm curious as to the cpu/memory/etc usage of a while(true) loop. The
>>> `top` command shows that the process is in the sbwait state (the OS is
>>> FreeBSD). I'm contemplating adding a usleep or even a sleep inside to
>>> loop. Would this be beneficial? I'm not too sure of how the internals
>>> of PHP work in terms of loops and such.
>>>
>>> Thanks.
>>>
>>> --
>>> PHP General Mailing List (http://www.php.net/)
>>> To unsubscribe, visit: http://www.php.net/unsub.php
>>>
>>>
>>
>> Is your socket blocking?  If so, what's the timeout?
>>
>> while(true) {
>>
>> //wait for socket timeout
>>
>> }
>>
>> is the same as:
>>
>> while(true) {
>>
>> //read nothing from socket and sleep
>>
>> }
>>
>> Without the usleep(), the loop is going to loop as fast as your CPU
>> will let it - meaning 100% CPU usage, all the time, at least in linux,
>> although I'm pretty sure BSD would behave the same.
>>
>> As far as I'm aware, sockets in PHP behave almost identically to the
>> way that they behave in C.  I had an asynchronous TCP server writte=
n
>> with the socket_* functions and noticed that the while(true) loop used
>> 100% of the CPU because of the nonblocking sockets in use, but a
>> usleep() solved that quite easily.  Using blocking sockets with
>> socket_select and a sane timeout relieved the high CPU usage as well.
>>
>
> I believe it is blocking. Here's my socket_recvfrom:
> $Recv =3D socket_recvfrom($Socket, $Data, 512, MSG_WAITALL, $Name, $Port)=
;
>
> So I think the the MSG_WAITALL is causing it to block until incoming
> data connection is closed (it never reaches the 512 byte mark before
> it echos the data). Here's the full script, minus the debugging/error
> catching stuff:
>
> $Socket =3D socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
> $Bind =3D socket_bind($Socket, '127.0.0.1', 1223);
> while(TRUE){
> $Recv =3D socket_recvfrom($Socket, $Data, 512, MSG_WAITALL, $Name, $Port)=
;
> print_r($Data);
> }
>
> As soon as the message is sent on the socket, it displays it. There's
> no delay until it builds up 512 bytes or anything. Also, I was playing
> around with ps and it looks like it's using 0% CPU, so I suppose it
> must be blocking.
>
> In the case that it is blocking, would it still be wise to throw a
> usleep in there just to be sure?
>
> Thanks.
>

MSG_WAITALL will block until 512 bytes of $Data has been received (or
a disconnect), so unless you're receiving a ridiculous amount of data
every iteration, forcing your CPU usage to be very high (which you've
said isn't the case :P) then there's no real reason to sleep every
while iteration. The reason why you're not getting a delay is because
your "clients" are not maintaining an open connection to the socket,
so it'll output as soon as the remote client disconnects from your
"server".

I wouldn't necessarily say it's unwise or wise to sleep after every
iteration, but it would depend on what kind of latency you need from
your application, how much data it's receiving, etc. etc. Another
thing you might want to consider about your design is that function,
as you're using it, blocks until those 512 bytes have been read, so if
a normal "request" (assuming a persistent connection) to your socket
is <512 bytes, it could potentially sit there and wait indefinitely
(not very likely). As it is, though, your server blocks (or sleeps,
if you will) on the socket until a connection is made and it reads 512
bytes / the client disconnects, which seems to be doing well for your
usage.

The old adage "if it ain't broke, don't fix it" sort of applies here.
Your program idles about at 0% CPU usage most of the time, for now.
Until something changes, I'd leave it alone :)

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Re: Performance of while(true) loop

am 10.09.2009 06:58:26 von Ben Dunlap

>>>> I have a php cli script that listens on a UDP socket and, when data is
[8<]
>> So I think the the MSG_WAITALL is causing it to block until incoming
>> data connection is closed (it never reaches the 512 byte mark before
[8<]
> your "clients" are not maintaining an open connection to the socket,
> so it'll output as soon as the remote client disconnects from your
> "server".
[8<]
> if you will) on the socket until a connection is made and it reads 512
> bytes / the client disconnects, which seems to be doing well for your
> usage.

Sorry if I'm missing something obvious, but do the concepts of
"connection", "close", and "disconnect" even apply in this case, since
it's a UDP socket?

Ben

--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Re: Performance of while(true) loop

am 10.09.2009 19:15:05 von List Manager

APseudoUtopia wrote:
> Hey list,
>
> I have a php cli script that listens on a UDP socket and, when data is
> sent to the socket, the script inserts it into a database. I'm using
> the real BSD socket functions, not fsock.
>
> The script runs socket_create(), then socket_bind(). Then it starts a
> while(TRUE) loop. Within the loop, it runs socket_recvfrom(). I have
> it running 24/7 inside a screen window.
>
> I'm curious as to the cpu/memory/etc usage of a while(true) loop. The
> `top` command shows that the process is in the sbwait state (the OS is
> FreeBSD). I'm contemplating adding a usleep or even a sleep inside to
> loop. Would this be beneficial? I'm not too sure of how the internals
> of PHP work in terms of loops and such.
>
> Thanks.
>


Here is something I wrote a few years ago. I still have this running on
my system today...

#!/usr/local/bin/php -q
error_reporting(E_ALL);
ini_set('display_errors', 'On');

// Set time limit to indefinite execution
set_time_limit(0);

// Set the ip and port we will listen on
define('LISTEN_IP', 'x.x.x.x'); // IP to listin on
define('LISTEN_PORT', 28000); // Port number to listen on
define('PACKET_SIZE', 512); // 512 bytes
define('SOCKET_TIMOUT', 2); // In Seconds

/* Open a server socket to port 1234 on localhost */
if ( $socket = @stream_socket_server('udp://'.LISTEN_IP.':'.LISTEN_PORT,
$errno, $errstr, STREAM_SERVER_BIND) ) {

echo "Running!!!\n";

while ( true ) {

// Output something to the screen to indicate that it is running
echo '.';

/* Get the exact same packet again, but remove it from the buffer
* this time.
*/
$buff = stream_socket_recvfrom($socket, PACKET_SIZE, 0, $remote_ip);

# Checking to see if someone is sending an invalid packet to my
# server
# Minimum packet size is 4 bytes
if ( strlen($buff) <= 4 ) {
continue;
}
print_r($buff);
}
fclose($socket);
}
echo "Done!!!\n";

###################END

Until recently, I was using screen also, but I have now switched over to
a new start/stop script. I run OpenBSD 4.3 & 4.5 on most of my boxes.

Once configured, this shell script can start/stop/status the given process.

I have been told that this does not start a /true/ daemon. But for me
it is close enough.

change the 4 variables at the top, just under the set -e line, and you
should have it.

Let me know if you have any problems.

#! /bin/ksh
#
# tms_daemon
#
# Starts a listening daemon that acts as a Tribes Master Server
#
# Author: Jim Lucas
#
# Version: 0.0.1
#

set -e

DESC="Name of service"
DAEMON=/path/to/file.php
PIDFILE=/var/run/.pid
SCRIPTNAME=tms_daemon

# Gracefully exit if the package has been removed.
test -x $DAEMON || exit 0

#
# Function that starts the daemon/service.
#
d_start() {
if [ -f $PIDFILE ]; then
echo "$DESC already running: PID# `cat $PIDFILE`"
exit 1
else
echo -n "Starting $DESC"
nohup $DAEMON 2>&1 1>/dev/null &
sleep 0.5
ps aux | grep $DAEMON | grep -v grep | awk -F' ' '{print $2} ' >
$PIDFILE
echo ". [`cat $PIDFILE`]"
fi
}

#
# Function that stops the daemon/service.
#
d_stop() {
if [ -f $PIDFILE ]; then
echo -n "Stopping $DESC"
kill `cat $PIDFILE`
rm $PIDFILE
echo "."
else
echo "$DESC is not running"
exit 1
fi
}

case "$1" in
start)
d_start
;;
stop)
d_stop
;;
status)
if [ -f $PIDFILE ]; then
echo "$DESC is running: PID# `cat $PIDFILE`"
else
echo "$DESC is not running"
fi
;;
cleanup)
PID="`ps aux | grep $DAEMON | grep -v grep | awk -F' ' '{print $2}'`"
kill $PID
rm $PIDFILE
;;
restart|force-reload)
d_stop
sleep 0.5
d_start
;;
*)
echo "Usage: $SCRIPTNAME {start|stop|restart|force-reload}" >&2
exit 1
;;
esac

exit 0

##############END


Jim Lucas


--
PHP General Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php