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木马攻击防御之道
Mar 24 PHP
PHP 程序授权验证开发思路
Jul 09 PHP
PHP验证码类代码( 最新修改,完全定制化! )
Dec 02 PHP
html静态页面调用php文件的方法
Nov 13 PHP
PHP中new static() 和 new self() 的区别介绍
Jan 09 PHP
PHPExcel读取EXCEL中的图片并保存到本地的方法
Feb 14 PHP
php多重接口的实现方法
Jun 20 PHP
php实现网页缓存的工具类分享
Jul 14 PHP
WordPress主题制作之模板文件的引入方法
Dec 28 PHP
Windows Server 2008 R2和2012中PHP连接MySQL过慢的解决方法
Jul 02 PHP
PHP微信企业号开发之回调模式开启与用法示例
Nov 25 PHP
Yii框架组件的事件机制原理与用法分析
Apr 07 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
解析zend studio中直接导入svn中的项目的方法步骤
2013/06/21 PHP
destoon常用的安全设置概述
2014/06/21 PHP
PHP7常量数组用法分析
2016/09/26 PHP
PHP中SERIALIZE和JSON的序列化与反序列化操作区别分析
2016/10/11 PHP
php运行报错Call to undefined function curl_init()的最新解决方法
2016/11/20 PHP
ThinkPHP实现生成和校验验证码功能
2017/04/28 PHP
javascript中的onkeyup和onkeydown区别介绍
2013/04/28 Javascript
JQuery 图片滚动轮播示例代码
2014/03/24 Javascript
JS字符串拼接在ie中都报错的解决方法
2014/03/27 Javascript
Javascript 完美运动框架(逐行分析代码,让你轻松了运动的原理)
2015/01/23 Javascript
JavaScript实现更改网页背景与字体颜色的方法
2015/02/02 Javascript
JS读写CSS样式的方法汇总
2016/08/16 Javascript
HTML5 canvas 9绘制图片实例详解
2016/09/06 Javascript
js实现滑动到页面底部自动加载更多功能
2017/02/15 Javascript
微信小程序 获取session_key和openid的实例
2017/08/17 Javascript
微信小程序实现传参数的几种方法示例
2018/01/10 Javascript
在Vue中使用highCharts绘制3d饼图的方法
2018/02/08 Javascript
Angular CLI在Angular项目中如何使用scss详解
2018/04/10 Javascript
深入理解使用Vue实现Context-Menu的思考与总结
2019/03/09 Javascript
从0搭建vue-cli4脚手架
2020/06/17 Javascript
通过实例解析js可枚举属性与不可枚举属性
2020/12/02 Javascript
详解python实现读取邮件数据并下载附件的实例
2017/08/03 Python
手把手教你用python抢票回家过年(代码简单)
2018/01/21 Python
深入浅析Python传值与传址
2018/07/10 Python
Python抽象和自定义类定义与用法示例
2018/08/23 Python
详解python和matlab的优势与区别
2019/06/28 Python
150行Python代码实现带界面的数独游戏
2020/04/04 Python
基于python生成英文版词云图代码实例
2020/05/16 Python
使用Numpy对特征中的异常值进行替换及条件替换方式
2020/06/08 Python
html5构建触屏网站之touch事件介绍
2013/01/07 HTML / CSS
使用layui实现左侧菜单栏及动态操作tab项的方法
2020/11/10 HTML / CSS
法国在线购买汽车轮胎网站:123pneus.fr
2019/02/25 全球购物
英国奢侈品概念店:Base Blu
2019/05/16 全球购物
岗位安全生产责任书
2014/07/28 职场文书
委托函范文
2015/01/29 职场文书
如何让你的Nginx支持分布式追踪详解
2022/07/07 Servers