Introduction
You should use memory_get_usage(false)
because what you want is memory used not memory allocated.
What's the Difference
Your Google Mail
might have allocated 25MB
of storage for you but it does not mean that is what you have used at the moment.
This is exactly what the PHP doc was saying
Set this to TRUE to get the real size of memory allocated from system. If not set or FALSE only the memory used by emalloc() is reported.
Both arguments would return memory allocated relative to the memory limit but the main difference is:
memory_get_usage(false)
give the memory used by emalloc()
while memory_get_usage(true)
returns milestone which can be demonstration here Memory Mile Store
I want to know how close was the script to hit that limit.
That would take some maths and might only work in loops or specific use cases. Why do I say that?
Imagine
ini_set('memory_limit', '1M');
$data = str_repeat(' ', 1024 * 1024);
The above script would fail before you even get the chance to start start checking memory
.
As far as I know the only way I can check memory used for a variable or specific section of PHP is:
$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;
See Explanation, but if you are in a loop or recursive function you can use maximum memory usage to estimate safely when memory peak would be reached.
Example
ini_set('memory_limit', '1M');
$memoryAvailable = filter_var(ini_get("memory_limit"), FILTER_SANITIZE_NUMBER_INT);
$memoryAvailable = $memoryAvailable * 1024 * 1024;
$peakPoint = 90; // 90%
$memoryStart = memory_get_peak_usage(false);
$memoryDiff = 0;
// Some stats
$stat = array(
"HIGHEST_MEMORY" => 0,
"HIGHEST_DIFF" => 0,
"PERCENTAGE_BREAK" => 0,
"AVERAGE" => array(),
"LOOPS" => 0
);
$data = "";
$i = 0;
while ( true ) {
$i ++;
// Get used memory
$memoryUsed = memory_get_peak_usage(false);
// Get Difference
$memoryDiff = $memoryUsed - $memoryStart;
// Start memory Usage again
$memoryStart = memory_get_peak_usage(false);
// Gather some stats
$stat['HIGHEST_MEMORY'] = $memoryUsed > $stat['HIGHEST_MEMORY'] ? $memoryUsed : $stat['HIGHEST_MEMORY'];
$stat['HIGHEST_DIFF'] = $memoryDiff > $stat['HIGHEST_DIFF'] ? $memoryDiff : $stat['HIGHEST_DIFF'];
$stat['AVERAGE'][] = $memoryDiff;
$stat['LOOPS'] ++;
$percentage = (($memoryUsed + $stat['HIGHEST_DIFF']) / $memoryAvailable) * 100;
// var_dump($percentage, $memoryDiff);
// Stop your script
if ($percentage > $peakPoint) {
print(sprintf("Stoped at: %0.2f", $percentage) . "%\n");
$stat['AVERAGE'] = array_sum($stat['AVERAGE']) / count($stat['AVERAGE']);
$stat = array_map(function ($v) {
return sprintf("%0.2f", $v / (1024 * 1024));
}, $stat);
$stat['LOOPS'] = $i;
$stat['PERCENTAGE_BREAK'] = sprintf("%0.2f", $percentage) . "%";
echo json_encode($stat, 128);
break;
}
$data .= str_repeat(' ', 1024 * 25); // 1kb every time
}
Output
Stoped at: 95.86%
{
"HIGHEST_MEMORY": "0.71",
"HIGHEST_DIFF": "0.24",
"PERCENTAGE_BREAK": "95.86%",
"AVERAGE": "0.04",
"LOOPS": 11
}
Live Demo
This may still fail
It may fail because after if ($percentage > $peakPoint) {
this still still add to do additional task with also consumes memory
print(sprintf("Stoped at: %0.2f", $percentage) . "%\n");
$stat['AVERAGE'] = array_sum($stat['AVERAGE']) / count($stat['AVERAGE']);
$stat = array_map(function ($v) {
return sprintf("%0.2f", $v / (1024 * 1024));
}, $stat);
$stat['LOOPS'] = $i;
$stat['PERCENTAGE_BREAK'] = sprintf("%0.2f", $percentage) . "%";
echo json_encode($stat, 128);
break;
If the memory to process this request is greater than the memory available the script would fail.
Conclusion
It's not a perfect solution, but check for memory at intervals and if it exceeds the peak (eg 90%), exit
instantly and leave the fancy stuff