I have been playing with PHP sockets for some days when making a simple IRC bot for some other projects, the bot is up and running but i noticed that after a couple of hours it will have eaten up all memory available.
I have been doing some debugging with memory_get_usage() and after making sure that i null out all variables i use within my loops, the only thing that causes an increase in memory usage is "fgets()", and i cannot seem to figure out why it wont release its memory after using it.
Any ideas of what i have been doing wrong?
Psudo-code:
$this->socket = stream_socket_client(server, port);
stream_set_blocking($this->socket, 0);
stream_set_timeout($this->socket, 600);
while(true) {
usleep(500000);
$data = fgets($this->socket, 8192);
*wor开发者_C百科k with data if strlen > 0*
$data = null;
}
Note that i have disabled blocking so that the bot can do some background tasks even when there are no activity on the channels it is watching.
Memory usage before and after calling fgets (the same result with stream_get_line):
int(959504)
string(0) "" //Data returned from gets
int(967736)
Note that i am testing against an SSL-server, could this be some kind of SSL "overflow"?
Or if you want to look at the whole code for yourself: https://github.com/Ueland/VikingBot
According to https://bugs.php.net/bug.php?id=38962 it's bug which is reproduced in a specific php 5.2.6 version. So if you use higher version you can report about your findings :)
Simply setting a variable to null doesn't release the memory the previous data was using. It simply disconnects the data from the variable. At some point in the future, the PHP garbage collector MAY kick in and actually free up the memory, but it's not guaranteed to do so. Garbage collection is a very expensive operation, CPU-usage-wise, and PHP will not run the GC unless it absolutely has to. Usually this'd be when memory usage gets close to the memory_limit
setting.
You can try to force a GC run via gc_collect_cycles()
use stream_get_line() instead of fgets()
Figured it out at last. I realized that instead of doing a "while(true)" i used a function that only called itself when it was done, and therefore keeping a reference of itself laying around. Dunno why i didnt notice it before now, but at least now the memory usage keeps the same for every round. ;)
Thanks for all suggestions!
精彩评论