PHP memory_get_usage

8

我发现了PHP的memory_get_usage()memory_get_peak_usage()

问题在于,我发现这两个函数并没有提供当前脚本实际使用的内存。

我的测试脚本如下:

<?php

echo memory_get_usage();

echo '<br />';

$a = str_repeat('hello', 100000);

echo '<br />';

echo memory_get_usage();

echo '<br />';

echo memory_get_peak_usage();

?>

这将返回:

355120

5355216

5356008

你从中可以理解什么?

第一个值是在执行str_repeat()之前,因此它必须是0的值。

第二个值是处理后的值,如果有一个比0大但不是那么大的值是可以接受的。

第三个值是“峰值”,它略微大于第二个值,我认为它应该是处理微秒中的最大值。

那么,您认为当前脚本的实际内存消耗值应该是这样的吗:

memory_usage = the second memory usage - the first memory usage

peak_memory_usage = the third (peak_usage) - the first memory usage

这段文字涉及到IT技术,翻译如下:

计算结果如下:

1) 5355216 - 355120 = 5000096 字节

2) 5356008 - 355120 = 5000888 字节

如果是这样的话,我认为第一个值355120字节是Apache和其他模块使用的整个系统分配内存,因为在str_repeat()重复次数增加或减少时,第一个值从未更改,只有进程后面的两个值会增加或减少,但永远不会比第一个值小。

3个回答

7
好的,你第一个断言中的第一次memory_get_usage()应该为0是错误的。根据PHP文档:
返回当前分配给您的PHP脚本的内存量(以字节为单位)。
您的脚本正在运行,因此必须有一些内存分配给它。第一个调用通知您分配了多少内存。
你的第二个断言是str_repeat()不应该使用那么多内存,这并不是看整个情况。
你有一个字符串“hello”(使用5个字节)重复100,000次,总共500,000字节...最少。问题是,PHP如何执行此操作?他们是否使用了以下代码?(伪代码):
s = ""
for(i=0; i<100000; i++)
    s += "hello"

这段代码要求在每次for循环迭代时重新分配一个新的字符串。虽然我不能确定PHP如何实现str_repeat(),但你必须非常小心地使用内存以保持内存使用量的下降。从表面上看,它们在该函数中没有很好地管理内存。

第三点,峰值内存使用量和当前内存使用量之间的差异可能来自于调用str_repeat()函数所需的堆栈,以及该函数内部所需的任何局部变量。当函数返回时,该内存可能已被回收。

最后,Apache运行在不同的进程中,我们处理的是虚拟内存。Apache执行的操作不会影响memory_get_usage()函数的结果,因为进程不会"共享"虚拟内存。


在我的情况下,使用PHP 5.3.3,它给出了预期的几乎完全相同的500,000差异(请参见我在本主题中的答案)。 - mojuba
@majuba,确实,不同版本/编译的PHP之间似乎存在巨大的差异。非常有趣。 - riwalk

7

根据php手册,memory_get_usage返回的是分配给php的内存量,而不一定是实际使用的内存量。


那么我是否需要在脚本执行前减去分配的第一个内存量,然后再从执行脚本后分配的第二个内存量中减去?就像我在问题中演示的例子一样,以获取运行当前脚本所使用的实际内存? - medk
1
@mohamed87,不是的。那确实是你的脚本使用的内存量。PHP解释器使用内存,因此会增加你的脚本内存的使用量。 - riwalk
谢谢您的回复。但问题是,我想监控我的PHP脚本的内存使用情况,以便在共享主机上不会过度消耗资源。 - medk
2
@mohamed87,我无法更清楚地解释了。在查看内存使用情况时,您__必须__同时查看解释器正在使用的内存。要看到全貌。memory_get_usage()给出的数字是正确的数字。 - riwalk

2

在我的情况下(PHP 5.3.3 在 Mac OS X 10.5 上),你的脚本会输出:

323964

824176

824980

现在,第二个测量值与第一个之间的差为500212,这非常接近 "hello" 的长度(5)乘以100,000。所以我认为这里没有什么意外。峰值有点更大是因为在求值这些语句时进行了一些临时分配。

(你的其他问题已经得到回答)


非常有趣。看起来你的实现中的PHP代码比问题作者的代码要高效得多。非常非常有趣... - riwalk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接