Thinkphp memory leak? ThinkPHP内存泄露?

April 8th, 2013 by xrigher Leave a reply »

Recently I encountered a problem with writing scripts with ThinkPHP framework. My scripts usually take long time to finish and have lots of communication with Mysql. However I find with ThinkPHP it’s very easy to come across with problem of out of memory, even if I’ve set the memory limit for each script to 256MB, which is quiet high!

Today I finally decided to carefully check this problem. The first thing came into my mind was that this must have something to do with db operations since I’m have heavy mysql operations. So I write a small piece of code to test whether I was right. Here is the code:

public function test() {
$mdl = M('t3');
$i = 0;
while(++$i < 300) {
$mdl->where('id=1')->select();
if($i % 50 == 0) {
echo number_format(memory_get_usage()) . "
\n";
}
}
}

I run this code and found this memory usage kept increasing which indicates there really exists a memory leak. Here is a sample output:

4,125,264 
4,146,688 
4,169,136 
4,189,536 
4,211,984

And then I replaced select() with buildSql() which only builds the sql instead of querying the db, I found that the memory stopped increasing. So the problem locates in the db operations!

After diving a bit in the source code, I found that the cause is the function Db::debug() which utilizes function trace(). Here is the Db::debug() definition:

    protected function debug() {
        $this->modelSql[$this->model]   =  $this->queryStr;
        $this->model  =   '_think_';
        if (C('DB_SQL_LOG')) {
            G('queryEndTime');
            trace($this->queryStr.' [ RunTime:'.G('queryStartTime','queryEndTime',6).'s ]','','SQL');
        }
    }

I realized that at the moment my application is still in the debug mode, which by default set the DB_SQL_LOG true. So now the solution is obvious: simply switch off the sql log, either by defining it in the config file such as Conf/debug.php or set it dynamically like this C(‘DB_SQL_LOG’, false). Because my website is still under development thus I need it on. So I choose the latter to set it dynamically in my script file.

But how the memory leak happens still remains uncovered. I’ll check it later.

Advertisement

Leave a Reply