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 htmlspecialchars加强版
Feb 16 PHP
PHP中用接口、抽象类、普通基类实现“面向接口编程”与“耦合方法”简述
Mar 23 PHP
Trying to clone an uncloneable object of class Imagic的解决方法
Jan 11 PHP
PHP获取http请求的头信息实现步骤
Dec 16 PHP
MongoDB在PHP中的常用操作小结
Feb 20 PHP
php实现每天自动变换随机问候语的方法
May 12 PHP
PHP简单预防sql注入的方法
Sep 27 PHP
PHP实现ASCII码与字符串相互转换的方法
Apr 29 PHP
解析 thinkphp 框架中的部分方法
May 07 PHP
laravel实现一个上传图片的接口,并建立软链接,访问图片的方法
Oct 12 PHP
php设计模式之中介者模式分析【星际争霸游戏案例】
Mar 23 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
CodeIgniter php mvc框架 中国网站
2008/05/26 PHP
PHP字符串的连接的简单实例
2013/12/30 PHP
PHP使用DOMDocument类生成HTML实例(包含常见标签元素)
2014/06/25 PHP
mac环境中使用brew安装php5.5.15
2014/08/18 PHP
Yii使用ajax验证显示错误messagebox的解决方法
2014/12/03 PHP
使用php+swoole对client数据实时更新(一)
2016/01/07 PHP
详解PHP中websocket的使用方法
2016/09/15 PHP
浅谈PHP的exec()函数无返回值排查方法(必看)
2017/03/31 PHP
JavaScript写的一个自定义弹出式对话框代码
2010/01/17 Javascript
jQuery中.live()方法的用法深入解析
2013/12/30 Javascript
再JavaScript的jQuery库中编写动画效果的指南
2015/08/13 Javascript
AngularJS Bootstrap详细介绍及实例代码
2016/07/28 Javascript
获取当前月(季度/年)的最后一天(set相关操作及应用)
2016/12/27 Javascript
AngularJS中controller控制器继承的使用方法
2017/11/03 Javascript
在react-router4中进行代码拆分的方法(基于webpack)
2018/03/08 Javascript
angularJs提交文本框数据到后台的方法
2018/10/08 Javascript
详解vue配置后台接口方式
2019/03/29 Javascript
vue实现动态按钮功能
2019/05/13 Javascript
[01:03:09]完美世界DOTA2联赛PWL S2 Forest vs SZ 第二场 11.25
2020/11/26 DOTA
在Apache服务器上同时运行多个Django程序的方法
2015/07/22 Python
在Python中将函数作为另一个函数的参数传入并调用的方法
2019/01/22 Python
查看python安装路径及pip安装的包列表及路径
2019/04/03 Python
Python实现的企业粉丝抽奖功能示例
2019/07/26 Python
python写文件时覆盖原来的实例方法
2020/07/22 Python
Python如何爬取51cto数据并存入MySQL
2020/08/25 Python
Python实现自动整理文件的脚本
2020/12/17 Python
详解CSS3 rem(设置字体大小) 教程
2017/11/21 HTML / CSS
HTML5开发动态音频图的实现
2020/07/02 HTML / CSS
Java中各种基本数据类型的默认值都是什么
2016/12/22 面试题
个人简历中的自我评价范例
2013/10/29 职场文书
股权转让协议书
2014/04/12 职场文书
义务教育学校标准化建设汇报材料
2014/08/16 职场文书
六年级小学生评语
2014/12/26 职场文书
《正比例》教学反思
2016/02/23 职场文书
导游词之山东红叶谷
2019/10/31 职场文书
Vue Element-ui表单校验规则实现
2021/07/09 Vue.js