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和ACCESS写聊天室(七)
Oct 09 PHP
php header功能的使用
Oct 28 PHP
thinkphp中html:list标签传递多个参数实例
Oct 30 PHP
ThinkPHP安装和设置
Jul 27 PHP
CodeIgniter配置之config.php用法实例分析
Jan 19 PHP
thinkphp3.x中cookie方法的用法分析
May 19 PHP
Yii2.0 模态弹出框+ajax提交表单
May 22 PHP
php 删除指定文件夹的实例讲解
Jul 25 PHP
PHP二维关联数组的遍历方式(实例讲解)
Oct 18 PHP
ThinkPHP5.0框架控制器继承基类和自定义类示例
May 25 PHP
thinkPHP3.2.2框架行为扩展及demo示例
Jun 19 PHP
PHP通过文件保存和更新信息的方法分析
Sep 12 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
Re:从零开始的异世界生活 第2季 开播啦
2020/07/24 日漫
php 数组的一个悲剧?
2011/05/11 PHP
php去除html标记的原生函数详解
2015/01/27 PHP
php实现字符串首字母转换成大写的方法
2015/03/17 PHP
Yii框架多语言站点配置方法分析【中文/英文切换站点】
2020/04/07 PHP
event.srcElement+表格应用
2006/08/29 Javascript
jQuery的实现原理的模拟代码 -5 Ajax
2010/08/07 Javascript
Jquery练习之表单验证实现代码
2010/12/14 Javascript
鼠标移到图片上变大显示而不是放大镜效果
2014/06/15 Javascript
在JavaScript中处理字符串之fontcolor()方法的使用
2015/06/08 Javascript
jQuery leonaScroll 1.1 自定义滚动条插件(推荐)
2016/09/17 Javascript
简单谈谈React中的路由系统
2017/07/25 Javascript
详解用函数式编程对JavaScript进行断舍离
2017/09/18 Javascript
利用HBuilder打包前端开发webapp为apk的方法
2017/11/13 Javascript
JS实现的自定义map方法示例
2019/05/17 Javascript
微信小程序实现星级评价
2019/11/20 Javascript
js通过循环多张图片实现动画效果
2019/12/19 Javascript
小程序中设置缓存过期的实现方法
2020/01/14 Javascript
JavaScript React如何修改默认端口号方法详解
2020/07/28 Javascript
手写Vue源码之数据劫持示例详解
2021/01/04 Vue.js
原生微信小程序开发中 redux 的使用详解
2021/02/18 Javascript
Python中使用摄像头实现简单的延时摄影技术
2015/03/27 Python
python读取二进制mnist实例详解
2017/05/31 Python
PyTorch加载预训练模型实例(pretrained)
2020/01/17 Python
用 python 进行微信好友信息分析
2020/11/28 Python
使用numpngw和matplotlib生成png动画的示例代码
2021/01/24 Python
Weblogic的布署方式
2013/08/23 面试题
几个Linux面试题笔试题
2016/08/01 面试题
2014国庆节标语口号
2014/09/19 职场文书
党的群众路线教育实践活动学习笔记范文
2014/11/06 职场文书
佛光寺导游词
2015/02/10 职场文书
项目负责人岗位职责
2015/02/15 职场文书
公司优秀员工推荐信
2015/03/24 职场文书
2015暑假实习报告范文
2015/07/13 职场文书
创业计划书之个人工作室
2019/08/22 职场文书
MySql新手入门的基本操作汇总
2021/05/13 MySQL