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 相关文章推荐
实用函数5
Nov 08 PHP
php 输出双引号&quot;与单引号'的方法
May 09 PHP
过滤掉PHP数组中的重复值的实现代码
Jul 17 PHP
关于PHP内存溢出问题的解决方法
Jun 25 PHP
php与java通过socket通信的实现代码
Oct 21 PHP
PHP加密解密类实例分析
Apr 20 PHP
正确的PHP匹配UTF-8中文的正则表达式
May 13 PHP
浅谈PHP中output_buffering
Jul 13 PHP
php实现在多维数组中查找特定value的方法
Jul 29 PHP
php获取远程文件大小
Oct 20 PHP
PHP给文字内容中的关键字进行套红处理
Apr 12 PHP
PHP实现微信模拟登陆并给用户发送消息的方法【文字,图片,图文】
Jun 29 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上传、管理照片示例
2006/10/09 PHP
thinkPHP5.0框架环境变量配置方法
2017/03/17 PHP
Yii框架分页实现方法详解
2017/05/20 PHP
PHP实现绘制二叉树图形显示功能详解【包括二叉搜索树、平衡树及红黑树】
2017/11/16 PHP
PHP中abstract(抽象)、final(最终)和static(静态)原理与用法详解
2020/06/05 PHP
laravel与thinkphp之间的区别与优缺点
2021/03/02 PHP
当前流行的JavaScript代码风格指南
2014/09/10 Javascript
JavaScript使用二分查找算法在数组中查找数据的方法
2015/04/07 Javascript
AngularJS Module方法详解
2015/12/08 Javascript
原生JS实现九宫格抽奖效果
2017/04/01 Javascript
BootStrap表单验证 FormValidation 调整反馈图标位置的实例代码
2017/05/17 Javascript
vue 开发一个按钮组件的示例代码
2018/03/27 Javascript
JS实现数组深拷贝的方法分析
2019/03/06 Javascript
tweenjs缓动算法的使用实例分析
2019/08/26 Javascript
python中global用法实例分析
2015/04/30 Python
Python编程中运用闭包时所需要注意的一些地方
2015/05/02 Python
Python打包文件夹的方法小结(zip,tar,tar.gz等)
2016/09/18 Python
Python实现时钟显示效果思路详解
2018/04/11 Python
Python去除字符串前后空格的几种方法
2019/03/04 Python
Python图像处理PIL各模块详细介绍(推荐)
2019/07/17 Python
关于pycharm中pip版本10.0无法使用的解决办法
2019/10/10 Python
对Tensorflow中Device实例的生成和管理详解
2020/02/04 Python
python seaborn heatmap可视化相关性矩阵实例
2020/06/03 Python
Python的3种运行方式:命令行窗口、Python解释器、IDLE的实现
2020/10/10 Python
python爬虫线程池案例详解(梨视频短视频爬取)
2021/02/20 Python
利用CSS3的checked伪类实现OL的隐藏显示的方法
2010/12/18 HTML / CSS
HTML5 Canvas中使用用路径描画圆弧
2015/01/01 HTML / CSS
工艺员岗位职责
2014/02/11 职场文书
安踏广告词改编版
2014/03/21 职场文书
小学英语课后反思
2014/04/26 职场文书
竞选演讲稿范文大全
2014/05/12 职场文书
2014年班级工作总结范文
2014/12/23 职场文书
小学新教师个人总结
2015/02/05 职场文书
项目安全员岗位职责
2015/02/15 职场文书
倡议书的格式写法
2015/04/28 职场文书
2020优秀员工演讲稿(三篇)
2019/10/17 职场文书