Re: Command-line PHP script CPU usage goes sky-high, stays there--why?
| From: | M5 | Date: | Tue, 11 Dec 2007 06:05:58 +0000 |
| Subject: | Re: Command-line PHP script CPU usage goes sky-high, stays there--why? | ||
| References: | 1 2 3 4 5 | Groups: | php.general |
| Request: | Send a blank email to php-general+get-265665@lists.php.net to get a copy of this message | ||
Thanks Jim. Several good points here that I will look into. I've already moved the include() bits into function calls. (That's simple thing I should have corrected long ago.) The socket areas though I'm less sure about how to adjust, since networking programming isn't something I grok naturally.
On 10-Dec-07, at 9:57 PM, Jim Lucas wrote:
René Fournier wrote:But my understanding from the docs (where I used one of the examples as a template for the script) socket is that it could/would only fail on startup, that is if it can't perform stream_select() because it's unable to bind to with stream_socket_server(), or am I wrong?: "If the call fails, it will return FALSE and if the optional errno and errstr arguments are present they will be set to indicate the actual system level error that occurred in the system-level socket(), bind(), and listen() calls. If the value returned in errno is 0 and the function returned FALSE, it is an indication that the error occurred before the bind() call. This is most likely due to a problem initializing the socket. Note that the errno and errstr arguments will always be passed by reference." (http://www.php.net/manual/en/function.stream-socket-server.php) In other wrongs, mod_fd can't return FALSE once the socket_server has been created and bound to the specified IP... right?FWIW, here's the stripped-down skeleton of the server: As always, constructive criticism is very welcome. <?php $socket = stream_socket_server("tcp://127.0.0.1:9876", $errno, $errstr); if ($socket) {The follow part, I think, is where your problem is. This line tells the system to wait 1 second and then continue, whether you have an inbound connection or not.$master[] = $socket; $read = $master; $write = $master; while (1) { $read = $master; $write = $master;Then here you are testing for success or failure of the last call.$mod_fd = stream_select($read, $_w = NULL, $_e = NULL, 1);Problem, if you don't have a connection, then the will fail constantly. once every second X (times) the number of connections you have...if ($mod_fd === FALSE) { break; }
But only until the connection closes, or no longer blocks (goes away), in which case the program fcloses that socket and removes it from master[].Here, you are not removing the successful connections from $master, so it keeps growing.... on and on...for ($i = 0; $i < $mod_fd; ++$i) { if ($read[$i] === $socket) { // NEW SOCKET $conn = stream_socket_accept($socket, 900); $master[] = $conn; $key_num = array_search($conn, $master, TRUE); } else { $sock_data = fread($read[$i], 32768); if (strlen($sock_data) === 0) { // CONNECTION GONE $key_to_del = array_search($read[$i], $master, TRUE); fclose($read[$i]); unset($master[$key_to_del]); } elseif ($sock_data === FALSE) { // CONNECTION BROKEN $key_to_del = array_search($read[$i], $master, TRUE); fclose($read[$i]); unset($master[$key_to_del]); } else { // READ INCOMING DATA
Yes, I did that. It helps a bit with CPU.As for the includes, well, I would turn them into function calls and then have a different function for the different ways you want the program to react.
Just at header.inc, once.I didn't see anything about your DB connections. Are those located in the includes?// include (somefiles); // include (somefiles); // include (somefiles); // [ ... ] } } } } }?>
How long, on average, does your processing of the incoming data take? Because, to me, it looks like you might have a blocking problem with the in-coming connections. If the initial connection takes too long, then the following connections might be getting blocked. You might want to look into pcntl_* functions to do forking if you need it.The processing is pretty quick. I don't think that's a bottleneck. It basically just inserts the data into MySQL, not much processing actually.