PHP中copy on write写时复制机制介绍


Posted in PHP onMay 13, 2014

什么是写时复制(Copy On Write)?

答:在复制一个对象的时候并不是真正的把原先的对象复制到内存的另外一个位置上,而是在新对象的内存映射表中设置一个指针,指向源对象的位置,并把那块内存的Copy-On-Write位设置为1.这样,在对新的对象执行读操作的时候,内存数据不发生任何变动,直接执行读操作;而在对新的对象执行写操作时,将真正的对象复制到新的内存地址中,并修改新对象的内存映射表指向这个新的位置,并在新的内存位置上执行写操作。

这个技术需要跟虚拟内存和分页同时使用,好处就是在执行复制操作时因为不是真正的内存复制,而只是建立了一个指针,因而大大提高效率。但这不是一直成立的,如果在复制新对象之后,大部分对象都还需要继续进行写操作会产生大量的分页错误,得不偿失。所以COW高效的情况只是在复制新对象之后,在一小部分的内存分页上进行写操作。

在PHP 内核中同样使用了写时复制机制来避免在赋值时导致内存增加,比如我们在使用foreach循环体时,可以发现其中的奥秘,示例代码:

$m1 = memory_get_usage();
$str=<<<EOF
aaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaa
EOF;
$arr = explode("\n", $str);
$count=0;
foreach($arr as $v){
    $count++;
    //$v='aaaaaaaaaaaaaa';
}
$m2 = memory_get_usage();
echo $m2-$m1;

当我们执行此代码时会得到内存占用为:788

$m1 = memory_get_usage();
$str=<<<EOF
aaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaa
EOF;
$arr = explode("\n", $str);
$count=0;
foreach($arr as $v){
$count++;
$v='aaaaaaaaaaaaaa';
}
$m2 = memory_get_usage();
echo $m2-$m1;

当我们取消 //$v='aaaaaaaaaaaaaa';  的注释,此时内存占用数值为:840,注意内存增长了。

$m1 = memory_get_usage();
$str=<<<EOF
aaaaaaaaaaaaaa
aaaaaaaaaaaaaa
aaaaaaaaaaaaaa
EOF;
$arr = explode("\n", $str);
$count=0;
foreach($arr as &$v){
$count++;
//$v='aaaaaaaaaaaaaa';
}
$m2 = memory_get_usage();
echo $m2-$m1;

当我们将foreach中的$v 改写为 &$v 时,不管是否注释循环体中对$v的注释,我们都可以得到内存占用为:788

这里就说明了COW机制的介入,当我们在foreach循环中纯粹的只用到对$v 的读操作时,PHP内核会将$v这个变量的内存地址指向到$arr中数组这一索引的内存地址,并没有将数组中的数据复制一份给到变量$v,此时内存占用情况和使用&$v 是一样的。但当我们在循环体内对$v进行写操作时,写时复制机制就被激活了,此时PHP会重新开辟一段内存空间给到$v变量,而将原先$v指向数组的内存地址给断开了,此时内存必然就会增长了。

这里可以得出另外一个结论:当我们在读取大数据的时候,要注意COW机制引入的内存增长影响,同样避免不必要的对变量写,可以提高代码运行性能。

PHP 相关文章推荐
PHP+MYSQL开发工具及资源收藏
Jan 02 PHP
php 清除网页病毒的方法
Dec 05 PHP
php调用mysql数据 dbclass类
May 07 PHP
destoon安装出现Internal Server Error的解决方法
Jun 21 PHP
php数组保存文本与文本反编成数组实例
Nov 13 PHP
php中session_id()函数详细介绍,会话id生成过程及session id长度
Sep 23 PHP
PHP中使用array函数新建一个数组
Nov 19 PHP
php中final关键字用法分析
Dec 07 PHP
PHP生成图片缩略图类示例
Jan 12 PHP
ThinkPHP实现分页功能
Apr 28 PHP
PHP获取数组中指定的一列实例
Dec 27 PHP
thinkPHP5.1框架路由::get、post请求简单用法示例
May 06 PHP
php读取富文本的时p标签会出现红线是怎么回事
May 13 #PHP
php的慢速日志引起的Mysql错误问题分析
May 13 #PHP
PHP实现的MongoDB数据库操作类分享
May 12 #PHP
PHP中date与gmdate的区别及默认时区设置
May 12 #PHP
PHP三元运算的2种写法代码实例
May 12 #PHP
PHP入门之常量简介和系统常量
May 12 #PHP
PHP实现数字补零功能的2个函数介绍
May 12 #PHP
You might like
javascript题目,重写函数让其无限相加
2012/02/15 Javascript
Extjs中使用extend(js继承) 的代码
2012/03/15 Javascript
Javascript 鼠标移动上去 滑块跟随效果代码分享
2013/11/23 Javascript
JavaScript实现数组随机排序的方法
2015/06/26 Javascript
js实现正则匹配中文标点符号的方法
2015/12/23 Javascript
JS控制伪元素的方法汇总
2016/04/06 Javascript
对象转换为原始值的实现方法
2016/06/06 Javascript
使用jquery/js获取iframe父子级、同级获取元素的方法
2016/08/05 Javascript
Bootstrap modal 多弹窗之叠加显示不出弹窗问题的解决方案
2017/02/23 Javascript
Node.js操作redis实现添加查询功能
2017/05/25 Javascript
微信小程序 获取session_key和openid的实例
2017/08/17 Javascript
Vue.js实现表格渲染的方法
2018/09/07 Javascript
JavaScript中引用vs复制示例详析
2018/12/06 Javascript
9102年webpack4搭建vue项目的方法步骤
2019/02/20 Javascript
10个最受欢迎的 JavaScript框架(推荐)
2019/04/24 Javascript
vue.js实现备忘录demo
2019/06/26 Javascript
vue根据条件不同显示不同按钮的操作
2020/08/04 Javascript
python引入导入自定义模块和外部文件的实例
2017/07/24 Python
利用Python暴力破解zip文件口令的方法详解
2017/12/21 Python
Python读取Json字典写入Excel表格的方法
2018/01/03 Python
python如何获取当前文件夹下所有文件名详解
2019/01/25 Python
python PyQt5/Pyside2 按钮右击菜单实例代码
2019/08/17 Python
Django 自动生成api接口文档教程
2019/11/19 Python
Tensorflow 卷积的梯度反向传播过程
2020/02/10 Python
CSS3正方体旋转示例代码
2013/08/08 HTML / CSS
HTML5验证以及日期显示的实现详解
2013/07/05 HTML / CSS
goodhealth官方海外旗舰店:新西兰国民营养师
2017/12/15 全球购物
PatPat阿根廷:妈妈们的购物平台
2019/05/30 全球购物
集团公司党的群众路线教育实践活动工作总结
2014/03/03 职场文书
大学中国梦演讲稿
2014/04/23 职场文书
大班亲子运动会方案
2014/06/10 职场文书
社区精神文明建设汇报材料
2014/08/17 职场文书
护士优质服务演讲稿
2014/08/26 职场文书
感谢信
2019/04/11 职场文书
导游词之铁岭象牙山
2019/12/06 职场文书
JS实现页面炫酷的时钟特效示例
2022/08/14 Javascript