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();
    }
}

参考:

艺术就是不妥协

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

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

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

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

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

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

就这样吧。

点歪了自己的技能树

感觉自己的技能树越来越歪了

最近痴迷于量化交易,但是却没走上Python的道路。。。EasyLanguage搞起来!!!

前端补完计划

自从叶老板的训练营付费模式从“点卡”变成“月卡”之后,每天都有很强烈的紧迫感要滚去学习。果然稀缺才是获得专注红利的法宝。

在这忙忙碌碌的一年里,我的前端补完计划也磕磕绊绊的进行了一大半了。我也从一个只会 ctrl+c - ctrl+v 的彩笔变成了一个偶尔能自己敲几行的半吊子 -。-

刚开始决定好好学习一下前端,是因为去年在一个React的“布道会”上,听叶老板讲了React的各种高大上。看叶老板演示了React开发,瞬间就激动的不得了--这写法简直和[平行宇宙通用语言](http://www.php.net)的写法一模一样!!!学学学!以后写页面不求搜索引擎!!!

我记得差不多是去年十月份的样子,我刚拿到人生作为一名正式员工的第一笔工资。在下班的公交车上,就一边摇晃,一边给叶老板转账报名,现在想想还是有点心潮澎湃。是的,给叶老板打钱的时候我确实很激动,因为感觉自己换到了宝贵的知识。但事实证明,我只是换到了一张门票,更多的还需要自己去探索。

接下来大半年因为各种事情,前端补完计划只进行了不到50%...直到最近稍微有点空闲时间,我才决定赶紧完成「我的前端补完计划」。然而,我却发现我连网站的入口都找不到了。。。咨询叶老板之后才知道,他们的付费模式从之前的“点卡”改成“月付”了。在这里,我不得不批评一下网易!看看你们开的什么好头,广州的公司们都学坏了!我现在都不舍得登录WOW了。。。

瞎扯了半天没用的,下面来点正经的。其实叶老板的月付也是有好处的:月付模式下所有课程都可以学习。正好我借此机会过了一边CSS和JS的一些比较隐秘和重要的特性。

感觉之前直接去学习React简直太急功近利了。目标只是学会框架,而不是核心的技术。结果只是机械的记住了一些诡异的用法。最近看完了一些css和js的基础,回头再去看之前学习React时的一些迷雾,有种豁然开朗的感觉。知道了js中变量作用域的诡异规定、js中this的千变万化、神奇的原型链继承、坑爹的const(值对象值是常量,复杂对象中地址是常量),还有flex布局简直太好用了!!0.0

Keep going!

刚敲下这两个单词,脑中突然蹦出了<风之旅人>的结局。

人生不就是在无尽的征途中拼命的多走几步嘛!