- Simple Memory Management Tips In PHP (With Examples)
- TLDR – QUICK SLIDES
- TABLE OF CONTENTS
- PHP MEMORY PERFORMANCE TRACKING
- A) TRACK MEMORY USAGE
- B) TIME TAKEN TO EXECUTE
- TRACKING WITH TOOLS
- PHP MEMORY EFFICIENT CODING
- 1) READ LINE-BY-LINE FROM THE DATABASE
- 2) READ FILE LINE-BY-LINE
- 3) REMOVE USELESS VARIABLES
- 4) MANUALLY REMOVE TEMPORARY VARIABLES
- 5) DIRECT OUTPUT FROM THE DATABASE
- DOWNLOAD & NOTES
- SUPPORT
- EXAMPLE CODE DOWNLOAD
- EXTRA BITS & LINKS
- SETTING THE MEMORY LIMIT
- LINKS & REFERENCES
- INFOGRAPHIC CHEAT SHEET
- THE END
- Leave a Comment Cancel Reply
- Search
- Breakthrough Javascript
- Socials
- About Me
- memory_get_usage
- Parameters
- Return Values
- Examples
- See Also
- User Contributed Notes 15 notes
Simple Memory Management Tips In PHP (With Examples)
Welcome to a quick tutorial on memory management in PHP. Running out of memory from massive scripts? While the easy way is to install more memory into the server, I am pretty sure that is not the most efficient way.
We can do simple memory management in PHP, without any complex tools.
- Use memory_get_peak_usage() to track peak memory usage.
- Apply some changes to improve the script efficiency.
- Do not read entire files at once, read line-by-line.
- Do not fetch all entries from the database at once, fetch one-by-one.
- Use unset($VAR) to manually remove unused variables, and gc_collect_cycles() to activate the garbage collector.
- Reduce the number of temporary variables and dependency on third-party libraries.
That’s all. No “special tools” nor “advanced techniques” are required, just some simple changes to the script – Read on for the examples!
TLDR – QUICK SLIDES
TABLE OF CONTENTS
PHP MEMORY PERFORMANCE TRACKING
For this first section, let us walk through how to track memory usage and execution time – No special tools are required.
A) TRACK MEMORY USAGE
// (B) MEMORY USAGE WITH ARRAY IN MEMORY echo "WITH LARGE ARRAY IN MEMORY
"; echo "Current usage: " . memory_get_usage() . " bytes
"; echo "Peak usage: " . memory_get_peak_usage() . " bytes
"; // (C) MEMORY USAGE AFTER ARRAY IS REMOVED unset($arr); echo "AFTER ARRAY IS REMOVED
"; echo "Current usage: " . memory_get_usage() . " bytes
"; echo "Peak usage: " . memory_get_peak_usage() . " bytes";On my computer, the output is:
WITH LARGE ARRAY IN MEMORY Current usage: 6683280 bytes Peak usage: 6683360 bytes AFTER ARRAY IS REMOVED Current usage: 391744 bytes Peak usage: 6683360 bytes
- memory_get_usage() returns the current memory usage, at the specified line of the script.
- memory_get_peak_usage() returns the highest recorded memory usage, at the specified line of the script.
For the purpose of memory tracking, memory_get_peak_usage() will probably make more sense.
B) TIME TAKEN TO EXECUTE
// (C) TOTAL TIME TAKEN $time = microtime(true) - $time; echo "Time taken - $time secs";
Yes, this is not tracking memory usage but is an important metric nonetheless. We do not want a massive script to hog a huge chunk of memory for extended periods of time.
TRACKING WITH TOOLS
No “special tools” are required for performance tracking. But if you prefer “something advanced”, check out Xdebug.
PHP MEMORY EFFICIENT CODING
Now that we have eyes on memory usage and execution time, the next step is to improve the efficiency of the scripts. Here are a few simple tips to reduce memory usage.
1) READ LINE-BY-LINE FROM THE DATABASE
PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]); // (C) PREPARE SQL $stmt = $pdo->prepare("SELECT * FROM `TABLE`"); $stmt->execute(); // (D) BAD - FETCH ALL AT ONCE // $results = $stmt->fetchAll(); // foreach ($results as $r) < print_r($r); >// (E) PREFERRED - FETCH LINE-BY-LINE while ($r = $stmt->fetch()) < print_r($r); >// (F) CLOSE DATABASE CONNECTION if ($stmt !== null) < $stmt = null; >if ($pdo !== null) < $pdo = null; >// (G) PEAK MEMORY USED echo "PEAK USAGE - " . memory_get_peak_usage();
Need to output a huge list of records into HTML or to a document? Don’t fetch them all at once. Fetch and deal with the records one by one instead.
2) READ FILE LINE-BY-LINE
fclose($handle); // (D) PEAK MEMORY USED echo "PEAK USAGE - " . memory_get_peak_usage();
Same old story, don’t read a massive file into a single string at once. Read line-by-line instead.
3) REMOVE USELESS VARIABLES
Some of you code ninjas may laugh and brush this aside as “trivial”. How much memory can a single variable take? Well, the more useless variables you have floating around, the more memory the script consumes. Remove hundreds of such useless flags and variables in a huge project, and you will see a huge difference.
4) MANUALLY REMOVE TEMPORARY VARIABLES
Temporary flags, variables, arrays, and objects – We can manually remove them to reduce resource hogging. Garbage collection is quite smart in PHP, but we can also call gc_collect_cycles() to clear things up.
5) DIRECT OUTPUT FROM THE DATABASE
PDO::ERRMODE_EXCEPTION, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC ]); // (C) HTTP HEADERS header("Content-Type: application/octet-stream"); header("Content-Transfer-Encoding: Binary"); header("Content-disposition: attachment; filename=\"export.csv\""); // (D) PREPARE SQL $stmt = $pdo->prepare("SELECT * FROM `TABLE`"); $stmt->execute(); // (E) BAD - FETCH ALL AT ONCE // $results = $stmt->fetchAll(); // foreach ($results as $r) < echo implode(",", $r) . "\r\n"; >// (F) PREFERRED - FETCH & DIRECTLY OUTPUT while ($r = $stmt->fetch()) < echo implode(",", $r) . "\r\n"; >// (G) CLOSE DATABASE CONNECTION if ($stmt !== null) < $stmt = null; >if ($pdo !== null)
Remember the “read line-by-line” example earlier? This is kind of a follow-up. If you are creating a CSV file or outputting to HTML – Just directly output the records. Don’t need to go the roundabout way of fetching the all rows into a massive array first, then use a for loop to run through them.
DOWNLOAD & NOTES
Here is the download link to the example code, so you don’t have to copy-paste everything.
SUPPORT
600+ free tutorials & projects on Code Boxx and still growing. I insist on not turning Code Boxx into a «paid scripts and courses» business, so every little bit of support helps.
EXAMPLE CODE DOWNLOAD
Click here for the source code on GitHub gist, just click on “download zip” or do a git clone. I have released it under the MIT license, so feel free to build on top of it or use it in your own project.
EXTRA BITS & LINKS
That’s all for this guide, and here is a small section on some links that may be useful to you.
SETTING THE MEMORY LIMIT
If all else fails, the only way is to raise the memory limits in php.ini .
Or we can also set it in the script during runtime.
LINKS & REFERENCES
INFOGRAPHIC CHEAT SHEET
THE END
Thank you for reading, and we have come to the end of this guide. I hope that it has helped you with your project, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!
Leave a Comment Cancel Reply
Search
Breakthrough Javascript
Take pictures with the webcam, voice commands, video calls, GPS, NFC. Yes, all possible with Javascript — Check out Breakthrough Javascript!
Socials
About Me
W.S. Toh is a senior web developer and SEO practitioner with over 20 years of experience. Graduated from the University of London. When not secretly being an evil tech ninja, he enjoys photography and working on DIY projects.
Code Boxx participates in the eBay Partner Network, an affiliate program designed for sites to earn commission fees by linking to ebay.com. We also participate in affiliate programs with Bluehost, ShareASale, Clickbank, and other sites. We are compensated for referring traffic.
memory_get_usage
Returns the amount of memory, in bytes, that’s currently being allocated to your PHP script.
Parameters
Set this to true to get total memory allocated from system, including unused pages. If not set or false only the used memory is reported.
Note:
PHP does not track memory that is not allocated by emalloc()
Return Values
Returns the memory amount in bytes.
Examples
Example #1 A memory_get_usage() example
// This is only an example, the numbers below will
// differ depending on your system?php
echo memory_get_usage () . «\n» ; // 36640
$a = str_repeat ( «Hello» , 4242 );
echo memory_get_usage () . «\n» ; // 57960
echo memory_get_usage () . «\n» ; // 36744
See Also
User Contributed Notes 15 notes
To get the memory usage in KB or MB
function convert ( $size )
$unit =array( ‘b’ , ‘kb’ , ‘mb’ , ‘gb’ , ‘tb’ , ‘pb’ );
return @ round ( $size / pow ( 1024 ,( $i = floor ( log ( $size , 1024 )))), 2 ). ‘ ‘ . $unit [ $i ];
>echo convert ( memory_get_usage ( true )); // 123 kb
?>Note, that the official IEC-prefix for kilobyte, megabyte and so on are KiB, MiB, TiB and so on.
At first glance this may sound like «What the hell? Everybody knows, that we mean 1024 not 1000 and the difference is not too big, so what?». But in about 10 years, the size of harddisks (and files on them) reaches the petabyte-limit and then the difference between PB and PiB is magnificent.
Better to get used to it now. 🙂
memory_get_usage() is used to retrieve the memory allocated to PHP only (or your running script). But intuitively, many people expect to get the memory usage of the system, based on the name of the function.
So if you need the overall memory usage, following function might be helpful. If retrieves the memory usage either in percent (without the percent sign) or in bytes by returning an array with free and overall memory of your system. Tested with Windows (7) and Linux (on an Raspberry Pi 2):
// Returns used memory (either in percent (without percent sign) or free and overall in bytes)
function getServerMemoryUsage ( $getPercentage = true )
$memoryTotal = null ;
$memoryFree = null ;if ( stristr ( PHP_OS , «win» )) // Get total physical memory (this is in bytes)
$cmd = «wmic ComputerSystem get TotalPhysicalMemory» ;
@ exec ( $cmd , $outputTotalPhysicalMemory );// Get free physical memory (this is in kibibytes!)
$cmd = «wmic OS get FreePhysicalMemory» ;
@ exec ( $cmd , $outputFreePhysicalMemory );// Find free value
foreach ( $outputFreePhysicalMemory as $line ) if ( $line && preg_match ( «/^4+\$/» , $line )) $memoryFree = $line ;
$memoryFree *= 1024 ; // convert from kibibytes to bytes
break;
>
>
>
>
else
if ( is_readable ( «/proc/meminfo» ))
$stats = @ file_get_contents ( «/proc/meminfo» );if ( $stats !== false ) // Separate lines
$stats = str_replace (array( «\r\n» , «\n\r» , «\r» ), «\n» , $stats );
$stats = explode ( «\n» , $stats );// Separate values and find correct lines for total and free mem
foreach ( $stats as $statLine ) $statLineData = explode ( «:» , trim ( $statLine ));//
// Extract size (TODO: It seems that (at least) the two values for total and free memory have the unit «kB» always. Is this correct?
//// Total memory
if ( count ( $statLineData ) == 2 && trim ( $statLineData [ 0 ]) == «MemTotal» ) $memoryTotal = trim ( $statLineData [ 1 ]);
$memoryTotal = explode ( » » , $memoryTotal );
$memoryTotal = $memoryTotal [ 0 ];
$memoryTotal *= 1024 ; // convert from kibibytes to bytes
>// Free memory
if ( count ( $statLineData ) == 2 && trim ( $statLineData [ 0 ]) == «MemFree» ) $memoryFree = trim ( $statLineData [ 1 ]);
$memoryFree = explode ( » » , $memoryFree );
$memoryFree = $memoryFree [ 0 ];
$memoryFree *= 1024 ; // convert from kibibytes to bytes
>
>
>
>
>if ( is_null ( $memoryTotal ) || is_null ( $memoryFree )) return null ;
> else if ( $getPercentage ) return ( 100 — ( $memoryFree * 100 / $memoryTotal ));
> else return array(
«total» => $memoryTotal ,
«free» => $memoryFree ,
);
>
>
>function getNiceFileSize ( $bytes , $binaryPrefix = true ) if ( $binaryPrefix ) $unit =array( ‘B’ , ‘KiB’ , ‘MiB’ , ‘GiB’ , ‘TiB’ , ‘PiB’ );
if ( $bytes == 0 ) return ‘0 ‘ . $unit [ 0 ];
return @ round ( $bytes / pow ( 1024 ,( $i = floor ( log ( $bytes , 1024 )))), 2 ) . ‘ ‘ . (isset( $unit [ $i ]) ? $unit [ $i ] : ‘B’ );
> else $unit =array( ‘B’ , ‘KB’ , ‘MB’ , ‘GB’ , ‘TB’ , ‘PB’ );
if ( $bytes == 0 ) return ‘0 ‘ . $unit [ 0 ];
return @ round ( $bytes / pow ( 1000 ,( $i = floor ( log ( $bytes , 1000 )))), 2 ) . ‘ ‘ . (isset( $unit [ $i ]) ? $unit [ $i ] : ‘B’ );
>
>// Memory usage: 4.55 GiB / 23.91 GiB (19.013557664178%)
$memUsage = getServerMemoryUsage ( false );
echo sprintf ( «Memory usage: %s / %s (%s%%)» ,
getNiceFileSize ( $memUsage [ «total» ] — $memUsage [ «free» ]),
getNiceFileSize ( $memUsage [ «total» ]),
getServerMemoryUsage ( true )
);?>
The function getNiceFileSize() is not required. Just used to shorten size in bytes.