在 PHP 中跟踪内存使用情况
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2290611/
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
Tracking Memory Usage in PHP
提问by Tim Lytle
I'm trying to track the memory usage of a script that processes URLs. The basic idea is to check that there's a reasonable buffer before adding another URL to a cURL multi handler. I'm using a 'rolling cURL' concept that processes a URLs data as the multi handler is running. This means I can keep N connections active by adding a new URL from a pool each time an existing URL processes and is removed.
我正在尝试跟踪处理 URL 的脚本的内存使用情况。基本思想是在将另一个 URL 添加到 cURL 多处理程序之前检查是否存在合理的缓冲区。我正在使用“滚动 cURL”概念,该概念在多处理程序运行时处理 URL 数据。这意味着每次现有 URL 处理和删除时,我都可以通过从池中添加一个新 URL 来保持 N 个连接处于活动状态。
I've used memory_get_usage()with some positive results. Adding the real_usageflag helped (not really clear on the difference between 'system' memory and 'emalloc' memory, but system shows larger numbers). memory_get_usage()does ramp up as URLs are added then down as the URL set is depleted. However, I just exceeded the 32M limit with my last memory check being ~18M.
我已经使用memory_get_usage()了一些积极的结果。添加real_usage标志有帮助(不太清楚“系统”内存和“emalloc”内存之间的区别,但系统显示更大的数字)。memory_get_usage()确实会随着 URL 的添加而上升,然后随着 URL 集的耗尽而下降。然而,我刚刚超过了 32M 的限制,我上次的内存检查是 ~18M。
I poll the memory usage each time cURL multi signals a request has returned. Since multiple requests may return at the same time, there's a chance a bunch of URLs returned data at the same time and actually jumped the memory usage that 14M. However, if memory_get_usage()is accurate, I guess that's what's happening.
每次 cURL multi 表示请求已返回时,我都会轮询内存使用情况。由于多个请求可能同时返回,因此有可能一堆URL同时返回数据并实际跳过了14M的内存使用量。但是,如果memory_get_usage()准确的话,我想这就是正在发生的事情。
[Update: Should have run more tests before asking I guess, increased php's memory limit (but left the 'safe' amount the same in the script) and the memory usage as reported did jump from below my self imposed limit of 25M to over 32M. Then, as expected slowly ramped down as URLs where not added. But I'll leave the question up: Is this the right way to do this?]
[更新:在问我猜之前应该运行更多测试,增加了 php 的内存限制(但在脚本中保留了相同的“安全”数量)并且报告的内存使用量确实从低于我自己施加的限制 25M 跳到了超过 32M . 然后,正如预期的那样,随着未添加的 URL 逐渐减少。但我会留下这个问题:这是正确的做法吗?]
Can I trust memory_get_usage()in this way? Are there better alternative methods for getting memory usage (I've seen some scripts parse the output of shell commands)?
我可以这样信任memory_get_usage()吗?是否有更好的替代方法来获取内存使用情况(我见过一些脚本解析 shell 命令的输出)?
回答by StasM
real_usageworks this way:
real_usage这样工作:
Zend's memory manager does not use system malloc for every block it needs. Instead, it allocates a big block of system memory (in increments of 256K, can be changed by setting environment variable ZEND_MM_SEG_SIZE) and manages it internally. So, there are two kinds of memory usage:
Zend 的内存管理器不会为它需要的每个块使用系统 malloc。相反,它分配了一大块系统内存(以 256K 为增量,可以通过设置环境变量来更改ZEND_MM_SEG_SIZE)并在内部对其进行管理。所以,有两种内存使用:
- How much memory the engine took from the OS ("real usage")
- How much of this memory was actually used by the application ("internal usage")
- 引擎从操作系统中占用了多少内存(“实际使用量”)
- 应用程序实际使用了多少内存(“内部使用”)
Either one of these can be returned by memory_get_usage(). Which one is more useful for you depends on what you are looking into. If you're looking into optimizing your code in specific parts, "internal" might be more useful for you. If you're tracking memory usage globally, "real" would be of more use. memory_limitlimits the "real" number, so as soon as all blocks that are permitted by the limit are taken from the system and the memory manager can't allocate a requested block, there the allocation fails. Note that "internal" usage in this case might be less than the limit, but the allocation still could fail because of fragmentation.
其中任何一个都可以由 返回memory_get_usage()。哪一个对您更有用取决于您正在研究什么。如果您正在考虑优化特定部分的代码,“内部”可能对您更有用。如果您正在全局跟踪内存使用情况,“真实”会更有用。memory_limit限制“真实”数字,因此只要限制允许的所有块都从系统中取出并且内存管理器无法分配请求的块,分配就会失败。请注意,在这种情况下,“内部”使用量可能小于限制,但由于碎片,分配仍然可能失败。
Also, if you are using some external memory tracking tool, you can set this
environment variable USE_ZEND_ALLOC=0which would disable the above mechanism and make the engine always use malloc(). This would have much worse performance but allows you to use malloc-tracking tools.
此外,如果您正在使用一些外部内存跟踪工具,您可以设置此环境变量USE_ZEND_ALLOC=0,这将禁用上述机制并使引擎始终使用malloc(). 这会带来更糟糕的性能,但允许您使用 malloc 跟踪工具。
See also an article about this memory manager, it has some code examples too.
另请参阅有关此内存管理器的文章,它也有一些代码示例。
回答by Alix Axel
I also assume memory_get_usage()is safe but I guess you can compare both methods and decide for yourself, here is a function that parses the system calls:
我也假设memory_get_usage()是安全的,但我想你可以比较这两种方法并自己决定,这是一个解析系统调用的函数:
function Memory_Usage($decimals = 2)
{
$result = 0;
if (function_exists('memory_get_usage'))
{
$result = memory_get_usage() / 1024;
}
else
{
if (function_exists('exec'))
{
$output = array();
if (substr(strtoupper(PHP_OS), 0, 3) == 'WIN')
{
exec('tasklist /FI "PID eq ' . getmypid() . '" /FO LIST', $output);
$result = preg_replace('/[\D]/', '', $output[5]);
}
else
{
exec('ps -eo%mem,rss,pid | grep ' . getmypid(), $output);
$output = explode(' ', $output[0]);
$result = $output[1];
}
}
}
return number_format(intval($result) / 1024, $decimals, '.', '');
}
回答by SeanDowney
Use xdebug, as it was recently (January of 29th) updated to now include memory profiling information. It keeps track of the function calls and how much memory they consume. This allows you to get very insightful view into your code and at the very least sets you in a direction of being aware of the problems.
使用xdebug,因为它最近(1 月 29 日)更新为现在包含内存分析信息。它跟踪函数调用以及它们消耗了多少内存。这使您可以非常深入地了解您的代码,并且至少让您朝着意识到问题的方向前进。
The documentation is helpful, but essentially you, install it enable the profiling xdebug.profiler_enable = 1and give the output xdebug.profiler_output_dir=/some/pathto a tool such as qcachegrindto do the heavy lifting, letting visually see it.
该文档很有帮助,但本质上,您安装它可以启用分析xdebug.profiler_enable = 1并将输出提供给qcachegrind 之类xdebug.profiler_output_dir=/some/path的工具来完成繁重的工作,让您直观地看到它。
回答by Dr Hydralisk
Well I have never really had a memory problem with my PHP scripts so I do not think I could be of much help finding the cause of the problem but what I can recomend is that you get a PHP accelerator, you will notice a serious performance increase and memory usage with decline. Here is a list of accelerators and an article comparing a few of them (3x better performance with any of them)
好吧,我的 PHP 脚本从来没有真正遇到过内存问题,所以我认为我对查找问题的原因没有多大帮助,但我建议您使用 PHP 加速器,您会注意到性能显着提高和内存使用量下降。这是加速器列表和比较其中一些加速器的文章(与其中任何一种相比,性能提高 3 倍)
The benchmarks are 2 years old but you get the idea of the performance increases.
基准测试已有 2 年历史,但您会了解性能有所提高。
If you have to you can also increase you memory limit in PHP if you are still having problems even with the accelerator. Open up your php.ini and find:
如果您不得不使用加速器,如果您仍然遇到问题,您还可以增加 PHP 中的内存限制。打开你的 php.ini 并找到:
memory_limit = 32M;
and just increase it a little.
并稍微增加它。

