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中的字符串函数
Oct 09 PHP
PHP与MySQL开发中页面出现乱码的一种解决方法
Jul 29 PHP
Php注入点构造代码
Jun 14 PHP
PHP加速 eAccelerator配置和使用指南
Jun 05 PHP
php+mysql 实现身份验证代码
Mar 24 PHP
探讨PHP使用eAccelerator的API开发详解
Jun 09 PHP
解析关于wamp启动是80端口被占用的问题
Jun 21 PHP
thinkphp使用phpmailer发送邮件的方法
Nov 24 PHP
PHP使用trim函数去除字符串左右空格及特殊字符实例
Jan 07 PHP
PHP等比例压缩图片的实例代码
Jul 26 PHP
YII2.0框架行为(Behavior)深入详解
Jul 26 PHP
php array 转json及java 转换 json数据格式操作示例
Nov 13 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
PHP和MySql中32位和64位的整形范围是多少
2016/02/18 PHP
javascript web对话框与弹出窗口
2009/02/22 Javascript
jqPlot Option配置对象详解
2009/07/25 Javascript
图像替换新技术 状态域方法
2010/01/28 Javascript
jquery之empty()与remove()区别说明
2010/09/10 Javascript
JavaScript中判断函数是new还是()调用的区别说明
2011/04/07 Javascript
js获取input标签的输入值实现代码
2013/08/05 Javascript
javascript 兼容各个浏览器的事件
2015/02/04 Javascript
教你如何使用firebug调试功能了解javascript闭包和this
2015/03/04 Javascript
开启Javascript中apply、call、bind的用法之旅模式
2015/10/28 Javascript
轻松学习jQuery插件EasyUI EasyUI创建树形菜单
2015/11/30 Javascript
手机Web APP如何实现分享多平台功能
2016/08/19 Javascript
详解Vue.js动态绑定class
2016/12/20 Javascript
深入理解react-router@4.0 使用和源码解析
2017/05/23 Javascript
BootStrap Table 后台数据绑定、特殊列处理、排序功能
2017/05/27 Javascript
浅谈vue的踩坑路
2017/08/31 Javascript
微信小程序实现上传照片代码实例解析
2020/08/04 Javascript
[42:32]VP vs RNG 2019国际邀请赛淘汰赛 败者组 BO3 第一场 8.21.mp4
2020/07/19 DOTA
Python实现进程同步和通信的方法
2018/01/02 Python
Tensorflow实现卷积神经网络用于人脸关键点识别
2018/03/05 Python
python使用folium库绘制地图点击框
2018/09/21 Python
Python中字符串与编码示例代码
2019/05/20 Python
python中安装django模块的方法
2020/03/12 Python
Python经典五人分鱼实例讲解
2021/01/04 Python
Funko官方商店:源自美国,畅销全球搪胶收藏玩偶
2018/09/15 全球购物
医学生实习自荐信
2013/10/01 职场文书
计算机专业推荐信范文
2013/11/20 职场文书
自我鉴定书
2014/03/24 职场文书
爱国主义教育演讲稿
2014/08/26 职场文书
小学生作文评语集锦
2014/12/25 职场文书
2015年护士节活动总结
2015/02/10 职场文书
反腐倡廉观后感
2015/06/08 职场文书
早安问候语大全
2015/11/10 职场文书
《老人与海鸥》教学反思
2016/02/16 职场文书
毕业生的自我鉴定表范文
2019/05/16 职场文书
导游词之太原天龙山
2020/01/02 职场文书