php 如何确定变量的内存占用(大小)?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2192657/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to determine the memory footprint (size) of a variable?
提问by Piskvor left the building
Is there a function in PHP (or a PHP extension) to find out how much memory a given variable uses? sizeofjust tells me the number of elements/properties.
PHP(或PHP扩展)中是否有一个函数来找出给定变量使用了多少内存?sizeof只是告诉我元素/属性的数量。
memory_get_usagehelps in that it gives me the memory size used by the wholescript. Is there a way to do this for a single variable?
memory_get_usage有助于它为我提供整个脚本使用的内存大小。有没有办法为单个变量做到这一点?
Note that this is on a development machine, so loading extensions or debug tools is feasible.
请注意,这是在开发机器上,因此加载扩展或调试工具是可行的。
采纳答案by Vineet1982
You Probably need a Memory Profiler. I have gathered information fro SO but I have copied the some important thing which may help you also.
您可能需要一个内存分析器。我已经收集了 SO 的信息,但我复制了一些可能对您有帮助的重要内容。
As you probably know, Xdebug dropped the memory profiling support since the 2.* version. Please search for the "removed functions" string here: http://www.xdebug.org/updates.php
您可能知道,从 2.* 版本开始,Xdebug 放弃了内存分析支持。请在此处搜索“已删除的功能”字符串:http: //www.xdebug.org/updates.php
Removed functions
Removed support for Memory profiling as that didn't work properly.
删除的功能
删除了对内存分析的支持,因为它无法正常工作。
Other Profiler Options
其他探查器选项
php-memory-profiler
php内存分析器
https://github.com/arnaud-lb/php-memory-profiler. This is what I've done on my Ubuntu server to enable it:
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
And then in my code:
然后在我的代码中:
<?php
memprof_enable();
// do your stuff
memprof_dump_callgrind(fopen("/tmp/callgrind.out", "w"));
Finally open the callgrind.outfile with KCachegrind
最后callgrind.out用KCachegrind打开文件
Using Google gperftools (recommended!)
使用 Google gperftools(推荐!)
First of all install the Google gperftoolsby downloading the latest package here: https://code.google.com/p/gperftools/
首先通过在此处下载最新软件包来安装Google gperftools:https: //code.google.com/p/gperftools/
Then as always:
然后一如既往:
sudo apt-get update
sudo apt-get install libunwind-dev -y
./configure
make
make install
Now in your code:
现在在您的代码中:
memprof_enable();
// do your magic
memprof_dump_pprof(fopen("/tmp/profile.heap", "w"));
Then open your terminal and launch:
然后打开你的终端并启动:
pprof --web /tmp/profile.heap
pprofwill create a new window in your existing browser session with something like shown below:
pprof将在您现有的浏览器会话中创建一个新窗口,如下所示:


Xhprof + Xhgui (the best in my opinion to profile both cpu and memory)
Xhprof + Xhgui(我认为最好的同时配置 CPU 和内存)
With Xhprofand Xhguiyou can profile the cpu usage as well or just the memory usage if that's your issue at the moment. It's a very complete solutions, it gives you full control and the logs can be written both on mongo or in the filesystem.
使用Xhprof和Xhgui,您还可以分析 cpu 使用情况,或者如果这是您目前的问题,则仅分析内存使用情况。这是一个非常完整的解决方案,它给你完全的控制权,日志可以写在 mongo 或文件系统中。
For more details see here.
有关更多详细信息,请参阅此处。
Blackfire
黑火
Blackfire is a PHP profiler by SensioLabs, the Symfony2 guys https://blackfire.io/
Blackfire 是 Symfony2 的 SensioLabs 开发的 PHP 分析器https://blackfire.io/
If you use puphpetto set up your virtual machine you'll be happy to know it's supported ;-)
如果你使用puphpet来设置你的虚拟机,你会很高兴知道它是受支持的 ;-)
Xdebug and tracing memory usage
Xdebug 和跟踪内存使用情况
XDEBUG2is a extension for PHP. Xdebug allows you to log all function calls, including parameters and return values to a file in different formats.There are three output formats. One is meant as a human readable trace, another one is more suited for computer programs as it is easier to parse, and the last one uses HTML for formatting the trace. You can switch between the two different formats with the setting. An example would be available here
XDEBUG2是 PHP 的扩展。Xdebug 允许您记录所有函数调用,包括参数和以不同格式返回到文件的值。有三种输出格式。一个是人类可读的跟踪,另一个更适合计算机程序,因为它更容易解析,最后一个使用 HTML 来格式化跟踪。您可以通过设置在两种不同的格式之间切换。这里有一个例子
forp
前
forpsimple, non intrusive, production-oriented, PHP profiler. Some of features are:
forp简单、非侵入性、面向生产的 PHP 分析器。一些功能是:
measurement of time and allocated memory for each function
CPU usage
file and line number of the function call
output as Google's Trace Event format
caption of functions
grouping of functions
aliases of functions (useful for anonymous functions)
为每个函数测量时间和分配的内存
CPU使用率
函数调用的文件和行号
输出为 Google 的跟踪事件格式
功能说明
功能分组
函数的别名(对匿名函数有用)
DBG
DBG
DBGis a a full-featured php debugger, an interactive tool that helps you debugging php scripts. It works on a production and/or development WEB server and allows you debug your scripts locally or remotely, from an IDE or console and its features are:
DBG是一个全功能的 php 调试器,一个帮助你调试 php 脚本的交互式工具。它适用于生产和/或开发 WEB 服务器,并允许您从 IDE 或控制台在本地或远程调试脚本,其功能包括:
Remote and local debugging
Explicit and implicit activation
Call stack, including function calls, dynamic and static method calls, with their parameters
Navigation through the call stack with ability to evaluate variables in corresponding (nested) places
Step in/Step out/Step over/Run to cursor functionality
Conditional breakpoints
Global breakpoints
Logging for errors and warnings
Multiple simultaneous sessions for parallel debugging
Support for GUI and CLI front-ends
IPv6 and IPv4 networks supported
All data transferred by debugger can be optionally protected with SSL
远程和本地调试
显式和隐式激活
调用栈,包括函数调用、动态和静态方法调用,及其参数
通过调用堆栈导航,能够评估相应(嵌套)位置中的变量
步进/步进/步进/运行到光标功能
条件断点
全局断点
记录错误和警告
用于并行调试的多个同时会话
支持 GUI 和 CLI 前端
支持 IPv6 和 IPv4 网络
调试器传输的所有数据都可以选择使用 SSL 进行保护
回答by Tatu Ulmanen
There's no direct way to get the memory usage of a single variable, but as Gordon suggested, you can use memory_get_usage. That will return the total amount of memory allocated, so you can use a workaround and measure usage before and after to get the usage of a single variable. This is a bit hacky, but it should work.
没有直接的方法来获取单个变量的内存使用情况,但正如戈登建议的那样,您可以使用memory_get_usage. 这将返回分配的内存总量,因此您可以使用变通方法并测量前后使用情况以获取单个变量的使用情况。这有点hacky,但它应该可以工作。
$start_memory = memory_get_usage();
$foo = "Some variable";
echo memory_get_usage() - $start_memory;
Note that this is in no way a reliable method, you can't be sure that nothing else touches memory while assigning the variable, so this should only be used as an approximation.
请注意,这绝不是一种可靠的方法,您无法确定在分配变量时没有其他任何东西触及内存,因此这应该仅用作近似值。
You can actually turn that to an function by creating a copy of the variable inside the function and measuring the memory used. Haven't tested this, but in principle, I don't see anything wrong with it:
您实际上可以通过在函数内部创建变量的副本并测量使用的内存来将其转换为函数。尚未对此进行测试,但原则上,我认为没有任何问题:
function sizeofvar($var) {
$start_memory = memory_get_usage();
$tmp = unserialize(serialize($var));
return memory_get_usage() - $start_memory;
}
回答by Aistina
No, there is not. But you can serialize($var)and check the strlenof the result for an approximation.
不,那里没有。但是您可以serialize($var)检查strlen结果的近似值。
回答by para
In answer to Tatu Ulmanens answer:
回答 Tatu Ulmanens 的回答:
It should be noted, that $start_memoryitself will take up memory (PHP_INT_SIZE * 8).
需要注意的是,它$start_memory本身会占用内存(PHP_INT_SIZE * 8)。
So the whole function should become:
所以整个函数应该变成:
function sizeofvar($var) {
$start_memory = memory_get_usage();
$var = unserialize(serialize($var));
return memory_get_usage() - $start_memory - PHP_INT_SIZE * 8;
}
Sorry to add this as an extra answer, but I can not yet comment on an answer.
很抱歉将其添加为额外答案,但我还不能对答案发表评论。
Update: The *8 is not definate. It can depend apparently on the php version and possibly on 64/32 bit.
更新: *8 不是确定的。它显然取决于 php 版本,也可能取决于 64/32 位。
回答by Gordon
See:
看:
memory_get_usage()— Returns the amount of memory allocated to PHPmemory_get_peak_usage()— Returns the peak of memory allocated by PHP
memory_get_usage()— 返回分配给 PHP 的内存量memory_get_peak_usage()— 返回 PHP 分配的内存峰值
Note that this won't give you the memory usage of a specific variable though. But you can put calls to these function before and after assigning the variable and then compare the values. That should give you an idea of the memory used.
请注意,这不会为您提供特定变量的内存使用情况。但是您可以在分配变量之前和之后调用这些函数,然后比较这些值。这应该让您了解所使用的内存。
You could also have a look at the PECL extension Memtrack, though the documentation is a bit lacking, if not to say, virtually non-existent.
你也可以看看PECL 扩展 Memtrack,虽然文档有点缺乏,如果不是说,几乎不存在。
回答by Liviu Bund?
You could opt for calculating memory difference on a callback return value. It's a more elegant solution available in PHP 5.3+.
您可以选择计算回调返回值的内存差异。这是 PHP 5.3+ 中提供的更优雅的解决方案。
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;
回答by Adam
You can't retrospectively calculate the exact footprint of a variable as two variables can share the same allocated space in the memory
您无法追溯计算变量的确切占用空间,因为两个变量可以共享内存中相同的分配空间
Let's try to share memory between two arrays, we see that allocating the second array costs half of the memory of the first one. When we unset the first one, nearly all the memory is still used by the second one.
让我们尝试在两个数组之间共享内存,我们看到分配第二个数组的内存是第一个数组的一半。当我们取消第一个时,几乎所有的内存仍然被第二个使用。
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)
So we can't conclude than the second array uses half the memory, as it becomes false when we unset the first one.
所以我们不能断定第二个数组使用了一半的内存,因为当我们取消第一个数组时它会变为假。
For a full view about how the memory is allocated in PHP and for which use, I suggest you to read the following article: How big are PHP arrays (and values) really? (Hint: BIG!)
要全面了解 PHP 中的内存分配方式以及用途,我建议您阅读以下文章:PHP 数组(和值)到底有多大?(提示:大!)
The Reference Counting Basicsin the PHP documentation has also a lot of information about memory use, and references count to shared data segment.
PHP 文档中的Reference Counting Basics也有很多关于内存使用的信息,以及对共享数据段的引用计数。
The different solutions exposed here are good for approximations but none can handle the subtle management of PHP memory.
这里公开的不同解决方案适用于近似,但没有一个可以处理 PHP 内存的微妙管理。
- calculating newly allocated space
- 计算新分配的空间
If you want the newly allocated space after an assignment, then you have to use memory_get_usage()before and after the allocation, as using it with a copy does give you an erroneous view of the reality.
如果您想要在分配后新分配的空间,那么您必须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";
Remember that if you want to store the result of the first memory_get_usage(), the variable has to already exist before, and memory_get_usage()has to be called another previous time, and every other function also.
请记住,如果您想存储第一个的结果memory_get_usage(),该变量必须之前已经存在,并且memory_get_usage()必须在之前的另一个时间以及其他所有函数中调用。
If you want to echo like in the above example, your output buffer has to be already opened to avoid accounting memory needed to open the output buffer.
如果你想在上面的例子中回显,你的输出缓冲区必须已经打开,以避免打开输出缓冲区所需的内存。
- calculating required space
- 计算所需空间
If you want to rely on a function to calculate the required space to store a copy of a variable, the following code takes care of different optimizations:
如果您想依靠一个函数来计算存储变量副本所需的空间,以下代码负责不同的优化:
<?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
Note that the size of the variable name matters in the memory allocated.
请注意,变量名称的大小在分配的内存中很重要。
- Check your code!!
- 检查你的代码!!
A variable has a basic size defined by the inner C structure used in the PHP source code. This size does not fluctuate in the case of numbers. For strings, it would add the length of the string.
变量具有由 PHP 源代码中使用的内部 C 结构定义的基本大小。这个大小在数字的情况下不会波动。对于字符串,它将添加字符串的长度。
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;
If we do not take the initialization of the variable name into account, we already know how much a variable uses (in case of numbers and strings):
如果我们不考虑变量名的初始化,我们已经知道变量使用了多少(在数字和字符串的情况下):
44 bytes in the case of numbers
+ 24 bytes in the case of strings
+ the length of the string (including the final NUL character)
数字的情况下为 44 个字节
+ 24 字节的字符串
+ 字符串的长度(包括最后的 NUL 字符)
(those numbers can change depending on the PHP version)
(这些数字可能会因 PHP 版本而异)
You have to round up to a multiple of 4 bytes due to memory alignment. If the variable is in the global space (not inside a function), it will also allocate 64 more bytes.
由于内存对齐,您必须四舍五入为 4 字节的倍数。如果变量在全局空间中(不在函数内部),它还会再分配 64 个字节。
So if you want to use one of the codes inside this page, you have to check that the result using some simple test cases (strings or numbers) match those data taking into account every one of the indications in this post ($_GLOBAL array, first function call, output buffer, ...)
因此,如果您想使用此页面中的代码之一,您必须使用一些简单的测试用例(字符串或数字)检查结果是否与这些数据匹配,同时考虑到本文中的每一个指示($_GLOBAL 数组,第一个函数调用,输出缓冲区,...)
回答by Alan Bellows
I had a similar problem, and the solution I used was to write the variable to a file then run filesize() on it. Roughly like this (untested code):
我遇到了类似的问题,我使用的解决方案是将变量写入文件,然后在其上运行 filesize()。大致是这样的(未经测试的代码):
function getVariableSize ( $foo )
{
$tmpfile = "temp-" . microtime(true) . ".txt";
file_put_contents($tmpfile, $foo);
$size = filesize($tmpfile);
unlink($tmpfile);
return $size;
}
This solution isn't terribly fast because it involves disk IO, but it should give you something much more exact than the memory_get_usage tricks. It just depends upon how much precision you require.
这个解决方案不是非常快,因为它涉及磁盘 IO,但它应该给你比 memory_get_usage 技巧更准确的东西。这仅取决于您需要多少精度。
回答by Abdelilah
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;
}
回答by Arkh
Never tried, but Xdebug traces with xdebug.collect_assignments may be enough.
从未尝试过,但使用xdebug.collect_assignment 进行Xdebug 跟踪可能就足够了。

