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 相关文章推荐
IIS6的PHP最佳配置方法
Mar 19 PHP
mysql 搜索之简单应用
Apr 27 PHP
php 字符转义 注意事项
May 27 PHP
php生成缩略图填充白边(等比缩略图方案)
Dec 25 PHP
PHP 5.3新增魔术方法__invoke概述
Jul 23 PHP
php中strtotime函数用法详解
Nov 15 PHP
PHP通过反射动态加载第三方类和获得类源码的实例
Nov 27 PHP
yii2控制器Controller Ajax操作示例
Jul 23 PHP
php解决和避免form表单重复提交的几种方法
Aug 31 PHP
thinkphp 字母函数详解T/I/N/D/M/A/R/U
Apr 03 PHP
PHP闭包定义与使用简单示例
Apr 13 PHP
使用laravel的migrate创建数据表的方法
Sep 30 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
屏蔽浏览器缓存另类方法
2006/10/09 PHP
PHP结合Ueditor并修改图片上传路径
2016/10/16 PHP
ubutu 16.04环境下,PHP与mysql数据库,网页登录验证实例讲解
2017/07/20 PHP
PHP中in_array的隐式转换的解决方法
2018/03/06 PHP
Yii2框架redis基本应用示例
2018/07/13 PHP
PHP基于cookie实现统计在线人数功能示例
2019/01/16 PHP
PHP学习记录之常用的魔术常量详解
2019/12/12 PHP
40个有创意的jQuery图片和内容滑动及弹出插件收藏集之二
2011/12/31 Javascript
AngularJS中取消对HTML片段转义的方法例子
2015/01/04 Javascript
JavaScript学习笔记之基础语法
2015/01/22 Javascript
jQuery针对input的class属性写了多个值情况下的选择方法
2016/06/03 Javascript
angular forEach方法遍历源码解读
2017/01/25 Javascript
详解在Vue中通过自定义指令获取dom元素
2017/03/04 Javascript
zTree树形菜单交互选项卡效果的实现方法
2017/12/25 Javascript
Vue.js 十五分钟入门图文教程
2018/09/12 Javascript
Vue2.x Todo之自定义指令实现自动聚焦的方法
2019/01/08 Javascript
Vue中使用matomo进行访问流量统计的实现
2019/11/05 Javascript
在项目vue中使用echarts的操作步骤
2020/09/07 Javascript
[58:18]2018DOTA2亚洲邀请赛3月29日 小组赛B组 iG VS Mineski
2018/03/30 DOTA
python list语法学习(带例子)
2013/11/01 Python
使用python解析xml成对应的html示例分享
2014/04/02 Python
Django的分页器实例(paginator)
2017/12/01 Python
Django+zTree构建组织架构树的方法
2019/08/21 Python
Python内存映射文件读写方式
2020/04/24 Python
数控专业毕业生求职信范文
2013/09/21 职场文书
中文系学生自荐信范文
2013/11/13 职场文书
网络专业学生个人的自我评价
2013/12/16 职场文书
给民警的表扬信
2014/01/08 职场文书
两年的个人工作自我评价
2014/01/10 职场文书
员工薪酬福利制度
2014/01/17 职场文书
创文明城市标语
2014/06/16 职场文书
白莲教口号
2014/06/18 职场文书
工商局副局长个人对照检查材料
2014/09/25 职场文书
房屋所有权证明
2014/10/20 职场文书
关于倡议书的范文
2015/04/29 职场文书
Python基础数据类型tuple元组的概念与用法
2021/08/02 Python