PHP:循环中存在一些内存问题
我有一个类似以下的片段:PHP:循环中存在一些内存问题,php,memory,garbage-collection,Php,Memory,Garbage Collection,我有一个类似以下的片段: while (true) { $myObject = new Class(); $myOtherObject = $myObject->getSomeOtherObj(); ... $myArray = [1, 2, 3]; ... sleep(1); //Sleep at the end, to save CPU. } 这段代码应该作为守护程序服务运行,但我在实现这一点上遇到了很多困难 问题:每次迭代都会增加进程
while (true) {
$myObject = new Class();
$myOtherObject = $myObject->getSomeOtherObj();
...
$myArray = [1, 2, 3];
...
sleep(1); //Sleep at the end, to save CPU.
}
这段代码应该作为守护程序服务运行,但我在实现这一点上遇到了很多困难
问题:每次迭代都会增加进程内存的使用。好像在每个新的迭代中,一个新的$myObject
被实例化,但前一个仍然被分配在内存中,诸如此类
我试过:
- 取消设置循环末尾的所有变量(就在
sleep()之前)李>
- 将所有变量设置为
李>null
- 将它们封装在单独的函数中(
)while(true){doThis();}
- 手动调用
gc\u collect\u cycles()
- 将所有变量设置为
我知道这个答案在直接方面没有太大帮助(而且我没有足够的代表对这个问题发表评论),但它可能会让你走上正轨。我在这里整理我以前的评论。这并不能确切地解释如何释放分配的内存,但将引导您找到一种方法,以发现应用程序中的原因。这样,您就可以优化代码了 查找内存使用瓶颈通常是一项具有挑战性的任务。您可以从查看与I/O相关的调用开始,例如数据库查询、文件访问甚至网络。除了增加执行时间,有时这些操作还可以分配一些内存 如果您已经从I/O操作返回的资源中清除了内存,并且没有注意到分配内存的显著减少,那么下一步可能是使用Blackfire()之类的工具分析应用程序 Blackfire将为您提供每个函数调用的详细视图及其有关内存、CPU和执行时间的统计信息。有了这些数据,就可以检查哪些操作分配了过多的内存。当您将鼠标指针放在调用详细信息中的内存条上时,您可以找到此信息,如下所示:我的最佳猜测(由于缺乏所涉及类的内部知识)是类将其他对象指定为其属性(或者它们可能具有自引用),或者使用了数组(因为代码示例类似于实际情况)有一个对自身的引用,如果数组的大小很大,这将解释内存泄漏 如果有任何帮助,请查看php.net中的参考计数基础知识:
正如上面提到的@m1lt0n和@MartPluijmaekers一样,这可能是一个与对象引用相关的问题 我们不知道您的
Class()
类和getSomeOtherObj()
方法中有什么,所以我不能肯定地说什么,不过下面的代码片段可能可以帮助您确定情况是否如此
/* Here is your Class */
class Class {
public function __construct () {
$this->child = new AnotherClass( $this );
}
/* This is what you have to have ... */
protected function __destruct () {
unset( $this->child );
}
}
/* Here is the other class */
class AnotherClass {
public function __construct ( $parent ) {
$this->parent = $parent;
}
}
/* Infinite Loop */
while ( true ) {
$myObject = new Class();
$myOtherObject = $myObject->getSomeOtherObj();
$myArray = [1, 2, 3];
/* manually destroying the object */
$myObject->__destruct();
unset( $myObject );
/* rest of free-ing goes here ... */
sleep(1); //Sleep at the end, to save CPU.
}
这段代码应该是不言自明的。问题在于,您处于一个无限循环中,请求没有结束。PHP的垃圾收集器设计为在请求结束时处理,否则用户将无法访问。PHP设计为被调用和丢弃,而不是不确定地保持活动状态。H因此,我建议创建一个计时作业,定期重新启动php循环,从而结束请求并释放内存。有关详细信息,请参阅。在对该主题进行了大量研究之后,我终于确信没有办法手动强制释放内存或强制销毁对象开 然而,帮助我降低内存使用率(绝对防止无限内存堆叠是不可能的)的是认识到PHP中没有循环作用域,并且垃圾收集是在切换作用域时发生的 在C#或Java中,在
while(…){}
中创建的变量只能从循环中访问。这不是PHP的标准。在while
指令中创建的$myObject
可以在整个应用程序中访问
这意味着所提供的代码段最好呈现为:
while (true) {
myFunc();
}
function myFunc()
{
$myObject = new Class();
$myOtherObject = $myObject->getSomeOtherObj();
...
$myArray = [1, 2, 3];
...
sleep(1); //Sleep at the end, to save CPU.
}
将逻辑封装在函数中会强制改变作用域,这意味着每次迭代都会调用垃圾收集器。这解决了我的问题,但在某种程度上降低了我的RAM使用率
我从这次经历中了解到,PHP可能不适合这个特定的项目需求。我需要对内存进行更多的控制,而PHP不提供对创建/销毁对象的任何控制。一些本机函数不能正确释放内存(特别是那些做I/O、数据库访问和memcached的函数).你到底想做什么,这似乎是一个无限循环!无限循环是要避免的事情这是一个无限循环,因为这是一个守护进程服务。这将听到一些更改,永远不会退出。我真的需要解释守护进程服务的概念吗?@zairwolf你说的基本上是“要释放内存,请退出程序,然后重新启动”。这不是答案,这是一个非常糟糕的解决方法,在我的规范中是不可能的。你能用一个有用的
来处理循环吗?很可能[…]仍然有对c的引用