未显式取消设置时对象内存使用过多
我的一位同事编写了一个耗尽可用内存的脚本。我将其范围缩小到以下基本测试用例:
for ( $i = 0; $i <= 20; $i ++ ) {
echo memory_get_usage(). '<br />';
$Survey = new Survey( 14 );
echo memory_get_usage(). '<br /><br />';
}
exit('done');
这在第三次迭代时中断:
3116696
49123440
49123440
95518368
95518368
[E_ERROR] Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes)
我设法通过在循环中添加 unset()
调用来解决此问题:
for ( $i = 0; $i <= 20; $i ++ ) {
echo memory_get_usage(). '<br />';
$Survey = new Survey( 14 );
unset( $Survey );
echo memory_get_usage(). '<br /><br />';
}
exit('done');
现在脚本将执行 20迭代非常顺利,内存使用量相对恒定:
3116816
49123488
49123488
50691656
50691656
51088912
51088912
51079064
51079064
50535368
50535368
50809296
50809296
51033392
51033392
51157208
51157208
50543856
50543856
50892760
50892760
51045160
51045160
51132688
51132688
50535968
50535968
50968632
50968632
51058080
51058080
51143304
51143304
50562136
50562136
51067432
51067432
51067768
51067768
51170824
51170824
50551712
done
这让我很困惑!垃圾收集器不应该清理该对象吗,因为它的变量已被覆盖?我运行的是 PHP 5.3,因此循环引用不可能是导致此问题的原因。
A colleague of mine wrote a script that was exhausting the available memory. I narrowed it down to the following basic test case:
for ( $i = 0; $i <= 20; $i ++ ) {
echo memory_get_usage(). '<br />';
$Survey = new Survey( 14 );
echo memory_get_usage(). '<br /><br />';
}
exit('done');
This breaks on the third iteration:
3116696
49123440
49123440
95518368
95518368
[E_ERROR] Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes)
I managed to fix this, by simply adding an unset()
call in the loop:
for ( $i = 0; $i <= 20; $i ++ ) {
echo memory_get_usage(). '<br />';
$Survey = new Survey( 14 );
unset( $Survey );
echo memory_get_usage(). '<br /><br />';
}
exit('done');
Now the script goes through its 20 iterations nice and smooth, with a relatively constant memory usage:
3116816
49123488
49123488
50691656
50691656
51088912
51088912
51079064
51079064
50535368
50535368
50809296
50809296
51033392
51033392
51157208
51157208
50543856
50543856
50892760
50892760
51045160
51045160
51132688
51132688
50535968
50535968
50968632
50968632
51058080
51058080
51143304
51143304
50562136
50562136
51067432
51067432
51067768
51067768
51170824
51170824
50551712
done
This confuses me! Isn't the garbage collector supposed to clean up the object, as it's variable has been overwritten? I'm running PHP 5.3, so circular references can't be the cause of this problem.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
循环引用仍然可能是一个问题5.3 中:
Survey
中可能还存在一些占用内存的资源,占用了所有这些内存;观察到的行为应该是引用循环和此类资源的组合。Survey
到底包含什么内容?Circular references can still be a problem in 5.3:
There is probably also some memory-hogging resource inside
Survey
that takes up all of this memory; the observed behavior should be a combination of a ref cycle and such a resource.What's in
Survey
exactly?该问题是由循环引用和每个对象占用 1/3 可用内存的组合引起的。将代码更改为:
向我展示:
您可以清楚地看到,手动启动垃圾收集器会释放“孤立”对象占用的内存。我认为问题在于垃圾收集器没有足够的时间启动,因为对象太大了。
目前最简单的解决方案是添加
unset()
调用 - 从长远来看,我将研究使Survey
对象更加节省内存的方法。感谢 Jon 和 CodeCaster 为我指明了正确的方向!
The problem was caused by the combination of circular references and the objects taking up 1/3rd of the available memory each. Changing the code to this:
showed me:
You can clearly see that firing up the garbage collector manually frees up the memory taken up by the 'orphaned' object. I think the problem was there just was not enough time for the garbage collector to kick in, as the objects were so big.
The easiest solution for now is adding the
unset()
call - for the long term though I will be investigating ways to make theSurvey
object more memory-efficient.Thanks to Jon and CodeCaster for pointing me in the right direction!