PHP Memory Usage

In this tutorial I will demonstrate how to find the amount of memory a PHP script is using, and how to free resources used by MySQL objects.

Memory Consumption

Not long ago I wrote a PHP task script that would run in the background for several hours, executing several million database queries before it finished. I observed that system memory allocation for the process would increase as it ran, and by the time it finished it was using a fair amount. Knowing how the script was written I knew it wasn’t necessary for all this memory to be reserved for the duration; it was an accumulation of past object use and code execution. When the process was done, PHP would garbage collect properly, and the script never exceeded the maximum memory settings, but I wanted to do some housecleaning.

Modifying the script to clean up after itself didn’t take much work; I’ll show you how.

Tracking Down Memory Usage

First, I needed to know where in the code that the largest chunks of memory were being allocated. I accomplished this using PHP’s memory_get_usage() function. For clear output I wrote the following wrapper function:

// Output the memory usage to the console, with an optional message parameter.
public function MemStat($message = null) {
    if ($message) {
        echo ($message . ": " . memory_get_usage() . "\n");
    } else {
        echo ("MEMORY USAGE: " . memory_get_usage() . "\n");
    }
}

I then added calls to MemStat in various places of the code where I guessed greater memory consumption would take place.

Freeing Up MySQL Memory Objects

Right away I found the answer was in the database result set objects. Adding PHP’s mysql_free_result() function is what I needed to force garbage collection.

// get results
$result = mysql_query("...");
 
// loop through the results
while($row = mysql_fetch_assoc($result)){
 
    // ...
 
}
 
// garbage collection
mysql_free_result($result);

Garbage Collection In PHP

Keep in mind that in this case PHP did NOT leak memory. PHP still had a handle on the memory allocated and was still freeing memory properly, it was just waiting until the time it thought best; in this case when the script finished executing. My reason for using mysql_free_result() was only personal preference, since I wanted to keep system resources as low as possible.