概要
简短的推荐(来自更多的数据资料,见答案)
为了避免内存泄漏,您可以:
题
对于什么PHP可以使用内存,除了库和variables? 我监视内存,由variables和〜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脏:59672
所以,实际消费总量是〜74Mb。 另外我看到一些大的块与[anon]映射在我的pmap为什么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
注意:这不是一个完全的答案,而是OP所要求的信息,但是注释字段对于这个来说太短了……这些更多的工具是如何调试这类问题的。
Xdebug的文档非常全面 ,他们应该通过将文档复制到这里来告诉我如何使用它。 你给的脚本有点模糊,所以我没有自己做跟踪,但它会给你逐行的内存使用率的差异。
基本上将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
。
PHP与编译为单个二进制文件的C或CPP代码不同。 所有的脚本都在Zend虚拟机内执行。 而且大部分的内存都被虚拟机本身消耗掉了。 这包括加载的扩展使用的内存PHP进程使用的共享库(.so文件)和任何其他共享资源。
我不记得确切的源代码,但是我读到的地方是,PHP内部消耗了近70%的CPU周期,而只有30%的代码到达你的代码(如果我在这里错了,请纠正我)。 这与内存消耗没有直接关系,但应该介绍一下PHP的工作原理。
关于匿名块,我在另一个SO答案中找到了一些细节。 答案是关于Java,但也应该适用于PHP。
匿名块是通过malloc或mmap分配的“大”块 – 请参阅联机帮助页。 因此,它们与Java堆没有任何关系(除了整个堆应该存储在这个块中的事实之外)。
查看这篇文章的匿名内存页面的更多细节(匿名) https://techtalk.intersec.com/2013/07/memory-part-2-understanding-process-memory/
另请查看此幻灯片共享以了解有关PHP内存管理的更多详情http://www.slideshare.net/jpauli/understanding-php-memory
我会建议禁用一些扩展。 这应该可以节省一些未使用的内存。
首先创建一个数组,调查正在使用的内存
$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
– 比估计的多十八倍 。
下面是所涉及的不同组件的内存使用情况的简要总结:
| 64位| 32位 -------------------------------------------------- - zval | 24字节| 16个字节 +循环GC信息| 8个字节| 4字节 +分配标题| 16字节| 8个字节 ================================================== = zval(value)total | 48字节| 28个字节 ================================================== = 桶| 72字节| 36个字节 +分配标题| 16字节| 8个字节 +指针| 8个字节| 4字节 ================================================== = 桶(数组元素)total | 96字节| 48个字节 ================================================== = 总计| 144字节| 76字节
同样,对于大的静态数组,如果我像这样调用:
$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
。
希望这会有所帮助。
你看到的数字没有什么错,你不应该把它们合并起来,这只是“三倍”,你看到分开列出的库的不同部分(只读,可执行,可写),你的编号是正确的。