如何查找哪个 PHP 脚本正在泄漏内存?
我的专用服务器有 32GB 内存,内存不断增加,我现在必须每天重新启动它.这让我失去了客户和金钱.
My dedicated server has 32GB RAM and the memory just goes up and up constantly and I have to reboot it daily now. This is costing me customers and money.
我很难找到内存泄漏的位置.我在网上能找到的只是人们说使用 xdebug",但我找不到任何关于查找内存泄漏的 xdebug 教程.我试过在函数调用之前和之后打印 memory_get_usage 但这是正确的方法吗?
I am having a hard time finding where the memory leak is. All I can find online is people say "Use xdebug" but I haven't been able to find any xdebug tutorials on finding memory leaks. I have tried printing memory_get_usage before and after function calls but is that the right way to do it?
我有很多 php 脚本正在运行——有些来自访问者,有些来自 cron 作业——我需要找出其中的哪一个正在泄漏内存并尽快修复它,但我什至不知道如何确定一个给定的函数是否存在内存泄漏.
I have MANY php scripts running - some from visitors, others from cron jobs - and I need to find which one(s) of them is leaking memory and fix it ASAP but I don't even know how to determine if a given function is leaking memory or not.
我尝试在函数调用之前和之后打印 memory_get_usage,并且它上升,但是如果我多次调用该函数,它就不再上升.有人可以解释一下并告诉我如何简单轻松地判断 PHP 函数是否存在内存泄漏吗?
I have tried printing memory_get_usage before a function call and after, and it goes up, but then if I call the function more than once, it doesn't go up anymore. Can someone please explain this and tell me how I can simply and easily tell if a PHP function has a memory leak?
推荐答案
你可以做各种各样的事情,但首先你应该尽量避免产生内存泄漏.
You could do various things, but first you should try to avoid the creation of memory leaks in the first place.
让我澄清一下:PHP 是一种脚本语言,它不是为长时间运行的脚本设计的,因此它的内存管理不是市场上最好的.但为什么会这样呢?它的目的是在请求级别调用,因此它的运行范围非常小(不超过 2 - 3 秒).其他一切都应该放在后台.
Let me clarify: PHP is a scripting language and it is not designed for long running scripts, so it's memory management is not the best on the market. But why should it be? It's purpose is to be called on a request level so its running scope is quite small (not more than 2 - 3 seconds). Everything else should be put in the background.
如何防止内存泄漏?
如果您使用的是低于 5.4 的版本,则需要处理循环引用,因为它们不会被垃圾收集.
If you are at a version below 5.4 you need to take care of circle references, since those are not garbage collected.
如果您需要连续运行脚本,您可能会考虑不同的方法.尝试使用 while(true)
实现,但包装 supervisor
(http://supervisord.org) 在你的脚本周围,让它在它结束后被调用.这样您就可以 100% 确保永远不会发生内存泄漏.
If you need a script to be run continuously, you might think about a different approach. Do try a while(true)
implementation, but wrap supervisor
(http://supervisord.org) around your script, and let it be called after it ends. That way you make 100% sure you never get memory leaks.
您可以使用 xdebug
一一分析您的脚本并找出消耗了大量内存的地方.
You could use xdebug
to profile your scripts one by one and find out, where a lot of memory is consumed.
如果不再需要该类,您可以实现一个析构函数来取消设置所有引用.
You could implement a destructor to unset all you references if the class is not of any need anymore.
public function __destruct(){
$this->cleanup();
}
public function cleanup() {
//cleanup everything from attributes
foreach (get_class_vars(__CLASS__) as $clsVar => $_) {
unset($this->$clsVar);
}
//cleanup all objects inside data array
if (is_array($this->_data)) {
foreach ($this->_data as $value) {
if (is_object($value) && method_exists($value, 'cleanUp')) {
$value->cleanUp();
}
}
}
}
通读有关垃圾收集的 PHP 文档http://us3.php.net/手册/en/features.gc.php
避免使用全局变量,因为它们永远不会被垃圾回收,需要显式unset
.如果您使用的是 ZF 或 Symfony 之类的框架,那可能是不可能的,因为这样做会破坏功能.
Avoid global variables, because those are never garbage collected and need to be unset
explicitly. If you are using a Framework like ZF or Symfony that might not be possible, since you would break functionality if you do.
最后但并非最不重要的一点,我要再次强调,PHP 不适合长时间运行的脚本!如果你有事情要做,需要连续运行,你不应该因为 PHP 中的内存泄漏而崩溃,而是花时间学习更复杂的语言,比如 JAVA 或 C#.
Last but not least I want to emphasize once again, PHP is not suited for long running scripts! If you have things to do, that need to run continuously you should not crumble your head with memory leaks in PHP, but take the time to learn a more sophisticated language like JAVA or C#.
相关文章