写时复制(Copy-on-Write,也缩写为COW),顾名思义,就是在写入时才真正复制一份内存进行修改。 COW最早应用在*nix系统中对线程与内存使用的优化,后面广泛的被使用在各种编程语言中,如C++的STL等。 在PHP内核中,COW也是主要的内存优化手段。 在前面关于变量和内存的讨论中,引用计数对变量的销毁与回收中起着至关重要的标识作用。 引用计数存在的意义,就是为了使得COW可以正常运作,从而实现对内存的优化使用。

写时复制的作用

以下是一段代码:

<?php

var_dump(memory_get_usage());//先打印出当前内存情况

$arr = array_fill(0, 100000, 'tioncico');//生成一个0-100000键的数组

var_dump(memory_get_usage());//打印内存

$arr_copy = $arr;//把数组赋值给另一个

var_dump(memory_get_usage());//打印内存

$j=1;

foreach($arr_copy as $i) {//循环遍历该数组键值查看内存情况

    $j += count($i);

}

var_dump(memory_get_usage());//打印内存

也就是说,就算我们不使用引用,php变量在传值,赋值的情况,都是指向同一个内存,但是如果当$arr_copy的值改变了会怎么样呢?<?php

var_dump(memory_get_usage());

//$tipi = array_fill(0, 3, 'php-internal');

//不用array_fill的原因可自己试着打印下

$tipi[0]='php-internal';

$tipi[1]='php-internal';

$tipi[2]='php-internal';

 

var_dump(memory_get_usage());

 

$copy = $tipi;

 

xdebug_debug_zval('tipi', 'copy');

 

var_dump(memory_get_usage());

 

$copy[0] = '123';

 

xdebug_debug_zval('tipi', 'copy');

 

var_dump(memory_get_usage());

结果如下:(注意:该结果是php5.6web环境下的,php7的引用不同)

可看出,当$arr把值赋值给$arr_copy时,执行内存是没有明显变化的,并没有直接增加5443320内存量

甚至在之后的foreach遍历中,也是没有增加内存的.

因为当$arr赋值给$arr_copy时,并不是在内存中复制了整个$arr的值,而是将$arr_copy的值指向了$arr,相当于在取$arr_copy的数据时,指向的还是$arr存值的内存

也就是说,就算我们不使用引用,php变量在传值,赋值的情况,都是指向同一个内存,但是如果当$arr_copy的值改变了会怎么样呢?

<?php

var_dump(memory_get_usage());

//$tipi = array_fill(0, 3, 'php-internal');

//不用array_fill的原因可自己试着打印下

$tipi[0]='php-internal';

$tipi[1]='php-internal';

$tipi[2]='php-internal';

var_dump(memory_get_usage());

$copy = $tipi;

xdebug_debug_zval('tipi', 'copy');

var_dump(memory_get_usage());

$copy[0] = '123';

xdebug_debug_zval('tipi', 'copy');

var_dump(memory_get_usage());

结果如下:(注意:该结果是php5.6web环境下的,php7的引用不同)

可以看出,当$copy[0]值改变时,php将会给$copy[0]重新申请内存,然后赋之以新值,但不影响其他值的内存状态。
写时复制的最小粒度,就是zval结构体, 而对于zval结构体组成的集合(如数组和对象等),在需要复制内存时,将复杂对象分解为最小粒度来处理。
这样做就使内存中复杂对象中某一部分做修改时,不必将该对象的所有元素全部“分离”出一份内存拷贝, 从而节省了内存的使用。

(文中的xdebug_debug_zval是xdebug扩展中的函数,用于查看变量的引用信息)

以上就是phpCOW机制详解的详细内容,更多请关注php中文网其它相关文章!

phpCOW机制详解的更多相关文章

  1. 从mixin到new和prototype:Javascript原型机制详解

    从mixin到new和prototype:Javascript原型机制详解   这是一篇markdown格式的文章,更好的阅读体验请访问我的github,移动端请访问我的博客 继承是为了实现方法的复用 ...

  2. 浏览器 HTTP 协议缓存机制详解

    最近在准备优化日志请求时遇到了一些令人疑惑的问题,比如为什么响应头里出现了两个 cache control.为什么明明设置了 no cache 却还是发请求,为什么多次访问时有时请求里带了 etag, ...

  3. JVM的垃圾回收机制详解和调优

    JVM的垃圾回收机制详解和调优 gc即垃圾收集机制是指jvm用于释放那些不再使用的对象所占用的内存.java语言并不要求jvm有gc,也没有规定gc如何工作.不过常用的jvm都有gc,而且大多数gc都 ...

  4. ThreadPoolExecutor运转机制详解

    ThreadPoolExecutor运转机制详解 - 走向架构师之路 - 博客频道 - CSDN.NET 最近发现几起对ThreadPoolExecutor的误用,其中包括自己,发现都是因为没有仔细看 ...

  5. Linux 内存机制详解宝典

    Linux 内存机制详解宝典 在linux的内存分配机制中,优先使用物理内存,当物理内存还有空闲时(还够用),不会释放其占用内存,就算占用内存的程序已经被关闭了,该程序所占用的内存用来做缓存使用,对于 ...

  6. PHP的垃圾回收机制详解

    原文:PHP的垃圾回收机制详解 最近由于使用php编写了一个脚本,模拟实现了一个守护进程,因此需要深入理解php中的垃圾回收机制.本文参考了PHP手册. 在理解PHP垃圾回收机制(GC)之前,先了解一 ...

  7. Java 反射 设计模式 动态代理机制详解 [ 转载 ]

    Java 反射 设计模式 动态代理机制详解 [ 转载 ] @author 亦山 原文链接:http://blog.csdn.net/luanlouis/article/details/24589193 ...

  8. Android事件分发机制详解

    事件分发机制详解 一.基础知识介绍 1.经常用的事件有:MotionEvent.ACTION_DOWN,MotionEvent.ACTION_MOVE,MotionEvent.ACTION_UP等 2 ...

  9. Android Binder机制详解:手写IPC通信

    想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...

随机推荐

  1. Python匹马行天下之初识python!

    python的发展史 1989年,被称为龟叔的Guido在为ABC语言写插件时,产生了写一个简洁又实用的编程语言的想法,并开始着手编写.因为其喜欢Monty Python喜剧团,所以将其命名为pyth ...

  2. Reverses CodeForces - 906E (最小回文分解)

    题意: 给你两个串s和t,其中t是由s中选择若干个不相交的区间翻转得到的,现在要求求出最少的翻转次数以及给出方案. 1≤|s|=|t|≤500000 题解: 我们将两个字符串合成成T=s1t1s2t2 ...

  3. verifier 调试内存泄露

    没啥技术含量,都是老段子了, 这次记下来,只是我想说,我也做过,留个念相. 前置条件,电脑里面必须得有Verifier,有了之后把自己的驱动加进去, WinDBG上双机,然后就可以跑了,跑一段时间就可 ...

  4. 源码编译安装nginx详细步骤

    1.下载nginx源码包并解压 可在http://nginx.org/en/download.html下载.tar.gz的源码包,如(nginx-1.4.7.tar.gz) 下载后通过tar -xvz ...

  5. K8S之部署Dashboard

    转载声明 本文转载自:ASP.NET Core on K8S深入学习(2)部署过程解析与部署Dashboard 1.Yaml安装 下载yaml文件 wget https://raw.githubuse ...

  6. kaggle 实战 (1): PCA + KNN 手写数字识别

    文章目录 加载package read data PCA 降维探索 选择50维度, 拆分数据为训练集,测试机 KNN PCA降维和K值筛选 分析k & 维度 vs 精度 预测 生成提交文件 本 ...

  7. win10安装mysql__艰难的心路历程

    俺是新系统,嘿嘿嘿 首先,把下载好的压缩包解压到安装目录中,哪个盘可以. 第二,先创建my.ini文件,不然待会忘了.在文件中添加以下内容: [mysqld] port = basedir=C:\Wi ...

  8. 【Servlet】Servlet监听器

    一.Servlet监听器的概念 Servlet监听器是Servlet规范中定义的一种特殊类,用于监听ServletContext.HttpSession和ServletRequest等域对象的创建与销 ...

  9. MFC int转CString

    方法一. int iVar = 7489; char szBuf[100]; _itoa(iVar, szBuf, 10); CString ss(szBuf); SetDlgItemText(IDC ...

  10. 更改网卡名称以及重启网卡提示Determining if ip address x.x.x.x is already in use for device eth0

    安装系统完成后,在CentOS6.6下网卡名称变为em1,有些不太方便,还是改回eth0 修改grub配置文件,vi /boot/grub/grub.conf,增加如下红色字体 kernel /vml ...