如何确定一个variables的内存占用(大小)?

PHP(或PHP扩展)中是否有函数来查找给定variables使用多less内存? sizeof只是告诉我元素/属性的数量。

memory_get_usage有助于提供整个脚本使用的内存大小。 有没有办法做到这一点的单个variables?

请注意,这是在开发机器上,所以加载扩展或debugging工具是可行的。

你可能需要一个内存分析器。 我已经收集了所有的信息,但我已经复制了一些可能帮助你的重要事情。

正如你可能知道的那样,自从2. *版本以来,Xdebug放弃了内存分析支持。 请在这里search“删除的函数”string: http : //www.xdebug.org/updates.php

删除了function

由于无法正常工作,删除了对内存分析的支持。

其他分析器选项

PHP-存储器廓

https://github.com/arnaud-lb/php-memory-profiler 。 这是我在Ubuntu服务器上完成的,

 sudo apt-get install libjudy-dev libjudydebian1 sudo pecl install memprof echo "extension=memprof.so" > /etc/php5/mods-available/memprof.ini sudo php5enmod memprof service apache2 restart 

然后在我的代码中:

 <?php memprof_enable(); // do your stuff memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w")); 

最后用KCachegrind打开callgrind.out文件

使用Google gperftools(推荐!)

首先在这里下载最新的软件包来安装Google gperftools : https : //code.google.com/p/gperftools/

然后一如既往:

 sudo apt-get update sudo apt-get install libunwind-dev -y ./configure make make install 

现在在你的代码中:

 memprof_enable(); // do your magic memprof_dump_pprof(fopen("/tmp/profile.heap", "w")); 

然后打开你的terminal并启动:

 pprof --web /tmp/profile.heap 

pprof将在您现有的浏览器会话中创build一个新窗口,如下所示:

用memprof和gperftools进行PHP内存分析

Xhprof + Xhgui(在我看来最好的configurationCPU和内存)

有了XhprofXhgui,你可以分析CPU使用情况,或者只是内存使用情况,如果这是你的问题。 这是一个非常完整的解决scheme,它可以让你完全控制,日志可以写在mongo或文件系统中。

欲了解更多详情请参阅这里

黑火

Blackfire是SensioLabs的一个PHP profiler,Symfony2的家伙https://blackfire.io/

如果你使用puphpet来设置你的虚拟机,你会很高兴知道它的支持;-)

Xdebug和跟踪内存使用情况

XDEBUG2是PHP的扩展。 Xdebug允许你logging所有的函数调用,包括参数和返回值到不同格式的文件。有三种输出格式。 一个意思是人类可读的踪迹,另一个更适合计算机程序,因为它更容易parsing,最后一个使用HTML格式化跟踪。 您可以使用设置在两种不同的格式之间切换。 这里有一个例子

forp

福特简单,非侵入性,生产型,PHP分析器。 一些function是:

  • 测量每个function的时间和分配的内存

  • CPU使用率

  • 文件和函数调用的行号

  • 输出为Google的跟踪事件格式

  • function标题

  • function分组

  • 函数的别名(对匿名函数有用)

DBG

DBG是一个全function的PHPdebugging器,一个交互式工具,可以帮助您debuggingPHP脚本。 它可以在生产和/或开发WEB服务器上运行,并允许您从IDE或控制台本地或远程debugging脚本,其function如下:

  • 远程和本地debugging

  • 显式和隐式激活

  • 调用堆栈,包括函数调用,dynamic和静态方法调用,以及它们的参数

  • 通过调用堆栈导航,能够评估相应(嵌套)位置的variables

  • 步入/步出/跳过/运行到游标function

  • 条件断点

  • 全局断点

  • logging错误和警告

  • 多个同步会话进行并行debugging

  • 支持GUI和CLI前端

  • 支持IPv6和IPv4networking

  • debugging器传输的所有数据都可以使用SSL进行select性保护

有没有直接的方法来获取单个variables的内存使用情况,但正如Gordon所build议的那样,您可以使用memory_get_usage 。 这将返回分配的内存总量,因此您可以使用一种解决方法并衡量前后的使用情况,以获取单个variables的使用情况。 这有点冒失,但它应该工作。

 $start_memory = memory_get_usage(); $foo = "Some variable"; echo memory_get_usage() - $start_memory; 

请注意,这绝不是一个可靠的方法,您不能确定在分配variables时没有其他东西触及内存,所以这只能用作近似值。

您可以通过在函数内部创build一个variables的副本并测量所使用的内存来将其转换为函数。 没有testing过这个,但是原则上我看不出有什么问题:

 function sizeofvar($var) { $start_memory = memory_get_usage(); $tmp = unserialize(serialize($var)); return memory_get_usage() - $start_memory; } 

不,那里没有。 但是,你可以serialize($var)并检查结果的大小,以近似值。

回答Tatu Ulmanens回答:

需要注意的是, $start_memory本身会占用内存( PHP_INT_SIZE * 8 )。

所以整个function应该变成:

 function sizeofvar($var) { $start_memory = memory_get_usage(); $var = unserialize(serialize($var)); return memory_get_usage() - $start_memory - PHP_INT_SIZE * 8; } 

对不起,添加这个作为额外的答案,但我还不能评论答案。

更新:* 8不确定。 它可以明显取决于PHP版本和可能在64/32位。

看到:

  • memory_get_usage() – 返回分配给PHP的内存量
  • memory_get_peak_usage() – 返回由PHP分配的内存的峰值

请注意,这不会给你一个特定variables的内存使用情况。

你也可以看一下PECL的扩展Memtrack ,虽然文档有点缺乏,如果不是说,几乎不存在。

由于两个variables可以在内存中共享相同的已分配空间,因此无法追溯计算variables的确切空间

让我们试着在两个数组之间共享内存,我们看到分配第二个数组的成本是第一个数组的一半。 当我们解除第一个时,几乎所有的内存仍然被第二个使用。

 echo memory_get_usage()."\n"; // <-- 433200 $c=range(1,100); echo memory_get_usage()."\n"; // <-- 444348 (+11148) $d=array_slice($c, 1); echo memory_get_usage()."\n"; // <-- 451040 (+6692) unset($c); echo memory_get_usage()."\n"; // <-- 444232 (-6808) unset($d); echo memory_get_usage()."\n"; // <-- 433200 (-11032) 

所以我们不能总结第二个数组使用一半的内存,因为当我们取消第一个时,它变成了错误。

有关如何在PHP中分配内存以及为何使用内存的完整视图,我build议您阅读以下文章: PHP数组(和值)有多大? (提示:大!)

PHP文档中的引用计数基础知识还包含大量有关内存使用情况的信息,并且引用计入共享数据段。

这里公开的不同的解决scheme是很好的近似,但没有人可以处理微妙的PHP内存pipe理。

  1. 计算新分配的空间

如果你想在赋值之后新分配的空间,那么你必须在分配之前和之后使用memory_get_usage() ,因为使用它与副本确实会给你一个错误的现实观。

 // open output buffer echo "Result: "; // call every function once range(1,1); memory_get_usage(); echo memory_get_usage()."\n"; $c=range(1,100); echo memory_get_usage()."\n"; 

请记住,如果要存储第一个memory_get_usage()的结果,则该variables必须先前已经存在,而memory_get_usage()必须先前被调用,而其他函数也必须先前被调用。

如果要像上面的例子那样回显,那么必须已经打开输出缓冲区,以避免打开输出缓冲区所需的记帐内存。

  1. 计算所需空间

如果你想依靠一个函数来计算所需的空间来存储一个variables的副本,下面的代码负责不同的优化:

 <?php function getMemorySize($value) { // existing variable with integer value so that the next line // does not add memory consumption when initiating $start variable $start=1; $start=memory_get_usage(); // json functions return less bytes consumptions than serialize $tmp=json_decode(json_encode($value)); return memory_get_usage() - $start; } // open the output buffer, and calls the function one first time echo ".\n"; getMemorySize(NULL); // test inside a function in order to not care about memory used // by the addition of the variable name to the $_GLOBAL array function test() { // call the function name once range(1,1); // we will compare the two values (see comment above about initialization of $start) $start=1; $start=memory_get_usage(); $c=range(1,100); echo memory_get_usage()-$start."\n"; echo getMemorySize($c)."\n"; } test(); // same result, this works fine. // 11044 // 11044 

请注意,variables名称的大小在分配的内存中很重要。

  1. 检查你的代码!

一个variables具有由PHP源代码中使用的内部C结构定义的基本大小。 这个大小在数字的情况下不会波动。 对于string,它会添加string的长度。

 typedef union _zvalue_value { long lval; /* long value */ double dval; /* double value */ struct { char *val; int len; } str; HashTable *ht; /* hash table value */ zend_object_value obj; } zvalue_value; 

如果我们不考虑variables名的初始化,我们已经知道一个variables使用多less(在数字和string的情况下):

在数字的情况下是44个字节

&加; string的情况下为24个字节

&加; string的长度(包括最后的NUL字符)

(这些数字可以根据PHP版本而改变)

由于内存alignment,您必须四舍五入到四个字节的倍数。 如果variables在全局空间中(不在函数内部),它也会分配64个字节。

所以,如果你想使用这个页面中的一个代码,你必须检查使用一些简单的testing用例(string或数字)的结果是否匹配这些数据,考虑到这个post中的每一个指示($ _GLOBAL数组,第一个函数调用,输出缓冲区…)

您可以select计算callback返回值的内存差异。 这是PHP 5.3+中更优雅的解决scheme。

 function calculateFootprint($callback) { $startMemory = memory_get_usage(); $result = call_user_func($callback); return memory_get_usage() - $startMemory; } $memoryFootprint = calculateFootprint( function() { return range(1, 1000000); } ); echo ($memoryFootprint / (1024 * 1024)) . ' MB' . PHP_EOL; 

我有一个类似的问题,我使用的解决scheme是将variables写入文件,然后运行filesize()。 粗略的像这样(未经testing的代码):

 function getVariableSize ( $foo ) { $tmpfile = "temp-" . microtime(true) . ".txt"; file_put_contents($tmpfile, $foo); $size = filesize($tmpfile); unlink($tmpfile); return $size; } 

这个解决scheme不是非常快,因为它涉及到磁盘IO,但它应该给你比memory_get_usage技巧更精确的东西。 这取决于你需要多less精度。

从来没有尝试过,但Xdebug跟踪xdebug.collect_assignment可能就足够了。

 function mesure($var){ $start = memory_get_usage(); if(is_string($var)){ $newValue = $var . ''; }elseif(is_numeric($var)){ $newValue = $var + 0; }elseif(is_object($var)){ $newValue = clone $var; }elseif(is_array($var)){ $newValue = array_flip($var, []); } return memory_get_usage() - $start; } 

以下脚本显示单个variables的总内存使用情况。

 function getVariableUsage($var) { $total_memory = memory_get_usage(); $tmp = unserialize(serialize($var)); return memory_get_usage() - $total_memory; } $var = "Hey, what's you doing?"; echo getVariableUsage($var); 

看一下这个

http://www.phpzag.com/how-much-memory-do-php-variables-use/