分类 默认分类 下的文章

PHP 变量存储初探

前几天在排查一个系统BUG的时候发现一段很有意思的代码

$obj=Obj()::where()->get();//这里是eloquent方法,大概15K条数据
foreach($obj as $k=>$v){
        bar();
    if($v->user){//eloquent 的has one
        foo();
    }
}

这段代码撑爆了单线程128M的内存限制。原因就在循环中$v->user没有释放内存。根据PHP手册对foreach的描述,我们可以得知这里的$v是拷贝赋值,并不是引用赋值。那么为什么每次循环结束的时候,这些内存没有被回收?

答案在于php存储变量的方式中。PHP中的变量存在一个叫zval的结构体中,我们所用的$a,$b...都只是一个变量的标签,变量真正的值都存在zval容器中。其实每次循环结束$v所占用的内存都已经被回收,但是销毁的 $v只是一个符号,对象真正使用的空间并没有被回收。看完下面这段代码,就应该能很容易的了解到底发生了什么。

echo "<br/>----------- Init a -------------<br/>";
$a=new stdClass();
$a->foo=1;
xdebug_debug_zval('a');

echo "<br/>----------- Init b ------------<br/>";
$b=$a;
$b->foo="bar";
xdebug_debug_zval('a');
xdebug_debug_zval('b');

echo "<br/>----------- Unset b ------------<br/>";
unset($b);
xdebug_debug_zval('a');

这段代码将返回:

----------- Init a -------------
a:
(refcount=1, is_ref=0),
object(stdClass)[1]
  public 'foo' => (refcount=1, is_ref=0),int 1

----------- Init b ------------
a:
(refcount=2, is_ref=0),
object(stdClass)[1]
  public 'foo' => (refcount=1, is_ref=0),string 'bar' (length=3)
b:
(refcount=2, is_ref=0),
object(stdClass)[1]
  public 'foo' => (refcount=1, is_ref=0),string 'bar' (length=3)

----------- Unset b ------------
a:
(refcount=1, is_ref=0),
object(stdClass)[1]
  public 'foo' => (refcount=1, is_ref=0),string 'bar' (length=3)

这里销毁了$b,但是却并没有将对象销毁掉。所以,在上面的的foreach中,orm对象不停的叠加user中的属性,而一直没有被回收,最终撑爆了内存。

解决方案是我司zkq指点我的,他让我尝试下深拷贝,完美解决。

$obj=Obj()::where()->get();
foreach($obj as $k=>$v){
        $value = clone $v;//克隆一个对象
        bar();
    if($value->user){//使用克隆的对象,循环结束立刻销毁
        foo();
    }
}

参考:

艺术就是不妥协

这个标题看着有点俗,这是刚才看一档访谈崔健节目的标题。看完之后觉得以前一些困扰自己的东西好像找到了一些答案。所以我想写下来,以后再看看。

崔健在节目中有说到一些不能说的事情,“有很多人说不能谈论这些事情,谈论这些东西就要谈论血”。随便想想,就会想到有很多不能谈论的事情,只要说到不能谈论的事情,**不离十的都会想起这件事情。

根植于上一代人的恐惧,让下一代人不敢开口谈论。以前不明白为什么不公开否认或者是承认,现在才明白这种沉默的恐惧的力量。不知道在什么地方看到过这样一句话“公众会因为恐惧而交出更多的权利来确保自己在集体中的安全,而政客渴望权利”

美帝距离伊拉克十万八千里,终究因为“恐怖主义”的原因,美国人民的意志把伊拉克清洗了一遍。然而,在我的印象中,中东之前貌似没有伊斯兰国这么强大的恐怖组织。。。

前段时间的“徐玉玉”事件,被各大主流媒体密集的报道。媒体过分的热情让人嗅出了一种坏味道,然后关于互联网严格管制的法案就高票通过了。

有很多东西想写,但是又不想写了。

就这样吧。