mysqli_result::free increase php memory usage

2019-07-11 01:59发布

问题:

Sometimes memory_get_usage() return a bigger value after using free(). See the example below:

$query = "SELECT * FROM table";
$result = self::query($query);

while ($row = $result->fetch_assoc())
{
    $myArray[] = $row;
}

echo "Before: ".number_format(memory_get_usage());
$result->free();
echo "After: ".number_format(memory_get_usage());

The output is:

Before: 1,203,856
After: 1,370,976

But if I comment the instruction in the loop then the memory usage decrease after the free():

$result = self::query($query);

while ($row = $result->fetch_assoc())
{
    //$myArray[] = $row;
}

echo "Before: ".number_format(memory_get_usage());
$result->free();
echo "After: ".number_format(memory_get_usage());

Gives:

Before: 593,120
After: 325,448

The result is quite big (~Mb) and there is a lot of text. It' only a few hundreds lines.

If the result has less than ~10 lines the memory usage always decrease.

My guess was that free() free the memory of MySQL and not php but then why does it usually decrease the php memory usage?

Can somebody explains what's going on here?

回答1:

If you are using mysql, rather than mysqli, take note of here:

http://dev.mysql.com/doc/apis-php/en/apis-php-mysqlnd.stats.html

Note that mysqlnd (unlike the MySQL Client Library) respects the PHP memory limit because it uses PHP internal memory management functions to allocate memory. This is also the reason why memory_get_usage reports a higher memory consumption when using mysqlnd instead of the MySQL Client Library. memory_get_usage does not measure the memory consumption of the MySQL Client Library at all because the MySQL Client Library does not use PHP internal memory management functions monitored by the function!

My best guess is: While the buffered result set still exists within the MySQL library, your $myArray has a reference to the same memory and thus memory is not considered used. However once you free the result set, the memory becomes "owned" or is otherwise transferred to your array and the memory usage is now counted.

This may not be entirely correct or the full story, but I would be fairly confident that this is the general gist of the issue.