PHP的 cow 和 zval 容器

什么是cow(copy on write)?

这是PHP一种内存优化的手段,可以节省内存空间的浪费,我们可以看看下面的例子。

<?php
 $a = range(0,20);
 var_dump(memory_get_usage());
 $b = $a;
 var_dump(memory_get_usage());
 $b = range(0,20);
 var_dump(memory_get_usage());

输出结果是:

我们可以看到,实际上执行$b = $a 这一句时,内存使用量并没有增加。只有改变b或者a的值时才会真正的复制一遍内存。如果这里你使用的是简单的字符串变量赋值,可能打印的内存使用量是一样的,这是因为当我们调用emalloc申请内存的时候, PHP并不是简单的向OS要内存, 而是会像OS要一个大块的内存, 然后把其中的一块分配给申请者, 这样当再有逻辑来申请内存的时候, 就不再需要向OS申请内存了, 避免了频繁的系统调用.(详细可以见鸟哥文章-深入理解PHP内存管理之谁动了我的内存: http://www.laruence.com/2011/03/04/1894.html),所以这里我采用的随机数组。

如果用图解释的话大致是这样的:

如果这里是$b = &a的话,就属于引用传递,指向的地址是相同的,就好比一个人有两个名字,例如鲁迅和周树人,如果鲁迅被抓了,说明周树人也被抓了,作用的实体是一样的,这里我就不画图说明了。

什么是zval?

它是PHP的一种容器,从PHP7开始, 对于在zval的value字段中能保存下的值, 就不再对他们进行引用计数了, 而是在拷贝的时候直接赋值, 这样就省掉了大量的引用计数相关的操作, 这部分类型有:

IS_LONG
IS_DOUBLE
当然对于那种根本没有值, 只有类型的类型, 也不需要引用计数了:

IS_NULL
IS_FALSE
IS_TRUE,例如123属于is_long,不进行引用计数所以为0,

举个栗子,看下列代码(在php7中安装了xdebug扩展才可执行):

<?php
 $a = 'mclink';
 xdebug_debug_zval('a');
 $b = &$a;
 xdebug_debug_zval('a');
 xdebug_debug_zval('b');
 $b = 'good';
 xdebug_debug_zval('b');

其中refcount是引用计数,is_ref为是否使用了引用,因为短字符串也算是IS_LONG类型的,所以第一个的refcount为0,is_ref也为0,然后b引用了a,所以a的refcount为2,这个东西不止它一个人用,还有另一个人。is_ref=1 说明所指向空间被引用了。

这里要注意的是:unset一个引用变量并不会释放其空间,只是取消了其引用。例如上例代码,如果我们unset($b),那么$a还是有值的,

对象的传递实际上就是一种引用传递

举栗子:

<?php
	class Test{
		public $name = 'xiaolu   ';

		public function  output()
		{
			echo $this->name;

		}

	}
	$a = new Test();
	$a->output(); //xiaolu 
	$b = $a;  //是引用传递,实际上是同个对象不同名称
	$b->name = 'mclink  ';
	$a->output(); //mclink

有关对象的引用,浅复制可以看我的另一篇文章说明:https://blog.csdn.net/qq_38378384/article/details/79850607

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MClink

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值