概要
简短的推荐(来自更多数据信息,请参阅答案)
为避免内存泄漏,您可以:
问题
什么php可以使用内存,除了库和变量? 我使用以下代码监视由变量及其~3Mb使用的内存:
$vars = array_keys(get_defined_vars());
$cnt_vars = count($vars);
$allsize = 0;
for ($j = 0; $j < $cnt_vars; $j++) {
try
{
$size = @serialize($$vars[$j]);
$size = strlen($size);
}
catch(Exception $e){
$str = json_encode($$vars[$j]);
$str = str_replace(array('{"','"}','":"','":'), '', $str);
$size = strlen($str);
}
$vars[$j] = array(
'size' => $size,
'name' => $vars[$j]
);
$allsize += $size;
}
和库需要~18Mb(libcurl等) 所以总计21 Mb,但
pmap -x(进程) 显示,总内存消耗为kB:314028 RSS:74704 Dirty:59672
所以,实际消费总量约为74Mb。 另外我在我的pmap中看到了一些带有[anon]映射的大块 对于使用此块的PHP?
php版本: 5.5.9-1ubuntu4.14 php扩展:
root@webdep:~# php -m
[PHP Modules]
bcmath
bz2
calendar
Core
ctype
curl
date
dba
dom
ereg
exif
fileinfo
filter
ftp
gd
gettext
hash
iconv
json
libxml
mbstring
mcrypt
mhash
openssl
pcntl
pcre
PDO
pdo_pgsql
pgsql
Phar
posix
readline
Reflection
session
shmop
SimpleXML
soap
sockets
SPL
standard
sysvmsg
sysvsem
sysvshm
tokenizer
wddx
xml
xmlreader
xmlwriter
Zend OPcache
zip
zlib
[Zend Modules]
Zend OPcache
答案 0 :(得分:5)
PHP与编译为单个二进制文件的C或CPP代码不同。所有脚本都在Zend虚拟机中执行。大多数内存都由VM本身消耗。这包括加载的扩展使用的内存,PHP进程使用的共享库(.so文件)和任何其他共享资源。
我不记得确切的来源,但在某处我读到,PHP内部消耗了近70%的总CPU周期,而且只有30%的内容被用于代码(如果我错了,请纠正我)。这与内存消耗没有直接关系,但应该了解PHP的工作原理。
关于anon block我在另一个SO答案中找到了一些细节。答案是关于Java的,但同样适用于PHP。
Anon块是通过malloc或mmap分配的“大”块 - 请参阅 联机帮助页。因此,它们与Java堆无关(其他 而不是整个堆应该存储在这样的事实中 块)。
以下是SO答案的实际链接 https://stackoverflow.com/a/1483482/1012809
查看本文以获取有关匿名内存页面(anon)的更多详细信息 https://techtalk.intersec.com/2013/07/memory-part-2-understanding-process-memory/
另请查看此幻灯片共享以获取有关PHP内存管理的更多详细信息 http://www.slideshare.net/jpauli/understanding-php-memory
我建议禁用一些扩展程序。这应该可以节省一些未使用的内存。
答案 1 :(得分:3)
注意:这不是答案,而是OP要求的信息,但评论字段对于此来说太短了......这些是更多的工具如何调试这类问题。
Xdebug’s docs are pretty comprehensive,他们应该通过将文档复制到此处来告诉我如何更好地使用它。你给的脚本有点模糊,所以我自己没有做跟踪,但它会给你逐行的内存使用差异。
基本上将xdebug.show_mem_delta
设置为1
并启用Xdebug以生成函数跟踪,然后可以在文本编辑器中打开该函数跟踪以查看泄漏内存的内容究竟是什么部分。
然后你可以比较初始(或中间位置)总内存,看它与你看到的实际内存使用量有多大差异。
TRACE START [2007-05-06 14:37:26]
0.0003 114112 +114112 -> {main}() ../trace.php:0
此处总内存为114112
。
如果差别很大,你可能想要使用类似shell_exec()
的东西来获取所有行之间的实际内存使用量,然后输出它,然后你可以将该输出与Xdebug的内存输出进行比较以查看差异发生的地方。
如果差异来自脚本的第一行,那么罪魁祸首可能是PHP的扩展。如果有任何可疑的扩展名,请参阅php -m
。
答案 2 :(得分:2)
首先制作一个数组,调查正在进行的记忆
$startMemory = memory_get_usage();
$array = range(1, 100000);
echo memory_get_usage() - $startMemory, ' bytes';
一个整数是8 bytes
(在64 bit unix machine
上使用long
类型)和100000 integers
,因此您显然需要800000 bytes
。这就像0.76 MB
。
此数组提供14649024 bytes
。那是13.97 MB
- 比估计值多出18倍。
以下是所涉及的不同组件的内存使用情况的快速摘要:
| 64 bit | 32 bit --------------------------------------------------- zval | 24 bytes | 16 bytes + cyclic GC info | 8 bytes | 4 bytes + allocation header | 16 bytes | 8 bytes =================================================== zval (value) total | 48 bytes | 28 bytes =================================================== bucket | 72 bytes | 36 bytes + allocation header | 16 bytes | 8 bytes + pointer | 8 bytes | 4 bytes =================================================== bucket (array element) total | 96 bytes | 48 bytes =================================================== total total | 144 bytes | 76 bytes
同样,对于大型静态数组,如果我称之为:
$startMemory = memory_get_usage();
$array = new SplFixedArray(100000);
for ($i = 0; $i < 100000; ++$i) {
$array[$i] = $i;
}
echo memory_get_usage() - $startMemory, ' bytes';
结果为5600640 bytes
每个元素56 bytes
,因此比普通数组使用的每个元素144 bytes
小得多。这是因为固定阵列不需要桶结构。因此,每个元素只需要一个zval (48 bytes)
和一个pointer (8 bytes)
,即可得到观察到的56 bytes
。
希望这会有所帮助。
答案 3 :(得分:0)
您看到的数字没有任何问题,您不应该将它们组合在一起,这只是“三倍”,您会看到单独列出的库的不同部分(只读,可执行,可写),您的数字是正确的。