memory_get_peak_usage() 与“实际使用”
如果参数设置为PHP DOCS,则表示它将获得从系统分配的实际内存大小。如果是,它将获得报告的内存real_usage
true
false
emalloc()
这 2 个选项中的哪一个返回相对于 php 中的内存限制值分配的最大内存.ini?
我想知道脚本达到这个限制有多近。
如果参数设置为PHP DOCS,则表示它将获得从系统分配的实际内存大小。如果是,它将获得报告的内存real_usage
true
false
emalloc()
这 2 个选项中的哪一个返回相对于 php 中的内存限制值分配的最大内存.ini?
我想知道脚本达到这个限制有多近。
好的,让我们使用一个简单的脚本来测试它:
ini_set('memory_limit', '1M');
$x = '';
while(true) {
echo "not real: ".(memory_get_peak_usage(false)/1024/1024)." MiB\n";
echo "real: ".(memory_get_peak_usage(true)/1024/1024)." MiB\n\n";
$x .= str_repeat(' ', 1024*25); //store 25kb more to string
}
输出:
not real: 0.73469543457031 MiB
real: 0.75 MiB
not real: 0.75910949707031 MiB
real: 1 MiB
...
not real: 0.95442199707031 MiB
real: 1 MiB
not real: 0.97883605957031 MiB
real: 1 MiB
PHP Fatal error: Allowed memory size of 1048576 bytes exhausted (tried to allocate 793601 bytes) in /home/niko/test.php on line 7
似乎真正的用法是从系统分配的内存 - 它似乎被分配到比脚本当前需要的更大的存储桶中。(我猜是出于性能原因)。这也是 php 进程使用的内存。
使用情况是您在脚本中实际使用的内存使用情况,而不是 Zend 内存管理器分配的实际内存量。$real_usage = false
有关详细信息,请阅读此问题。
简而言之:要获得您与内存限制的接近程度,请使用$real_usage = true
介绍
您应该使用,因为您想要的是使用的内存而不是分配的内存。memory_get_usage(false)
有什么区别
您可能已经为您分配了存储空间,但这并不意味着这是您目前使用的存储空间。Google Mail
25MB
这正是PHP文档所说的
将此值设置为 TRUE 可获取从系统分配的实际内存大小。如果未设置或 FALSE,则仅报告 emalloc() 使用的内存。
这两个参数都将返回相对于内存限制分配的内存,但主要区别在于:
memory_get_usage(false)
给出使用的内存,而返回里程碑可以在这里演示记忆英里存储emalloc()
memory_get_usage(true)
我想知道脚本达到这个限制有多近。
这需要一些数学计算,并且可能仅适用于循环或特定用例。为什么这么说呢?
想象
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
.
据我所知,我检查用于变量或PHP特定部分的内存的唯一方法是:
$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;
请参阅说明,但如果处于循环或递归函数中,则可以使用最大内存使用量来安全地估计何时达到内存峰值。
例
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
}
Stoped at: 95.86%
{
"HIGHEST_MEMORY": "0.71",
"HIGHEST_DIFF": "0.24",
"PERCENTAGE_BREAK": "95.86%",
"AVERAGE": "0.04",
"LOOPS": 11
}
这可能仍然会失败
它可能会失败,因为在此之后仍然添加以执行其他任务,同时也会消耗内存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;
If the memory to process this request is greater than the memory available the script would fail.
结论
这不是一个完美的解决方案,但每隔一段时间检查内存,如果它超过峰值(例如90%),立即离开花哨的东西exit