PHP中copy on write写时复制机制介绍

 更新时间:2014年05月13日 11:36:09   作者:  
这篇文章主要介绍了PHP中copy on write写时复制机制介绍,需要的朋友可以参考下

什么是写时复制(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机制引入的内存增长影响,同样避免不必要的对变量写,可以提高代码运行性能。

相关文章

  • 实现 win2003 下 mysql 数据库每天自动备份

    实现 win2003 下 mysql 数据库每天自动备份

    这篇文章主要为大家介绍下,如果用批处理实现mysql的自动备份,需要的朋友可以参考下
    2006-12-12
  • php数组对百万数据进行排除重复数据的实现代码

    php数组对百万数据进行排除重复数据的实现代码

    在平时的工作中,经常接到要对网站的会员进行站内信、手机短信、email进行群发信息的通知,用户列表一般由别的同事提供,当中难免会有重复,为了避免重复发送,所以我在进行发送信息前要对他们提供的用户列表进行排重,下面我以uid列表来讲讲我是如何利用php数组进行排重的。
    2010-06-06
  • 降低PHP Redis内存占用

    降低PHP Redis内存占用

    本文主要介绍了降低PHP Redis内存占用的方法。具有很好的参考价值。下面跟着小编一起来看下吧
    2017-03-03
  • php多数据库支持的应用程序设计

    php多数据库支持的应用程序设计

    以前做PHP应用,多数是单数据库数据查询和更新,顶多也是主从数据库的支持,实现起来相对简单。主从数据库的问题在于,当会话存储在数据库的时候,同步将可能出现问题,也就是说有可能出现会话的中断。
    2008-08-08
  • PHP使用file_get_content设置头信息的方法

    PHP使用file_get_content设置头信息的方法

    这篇文章主要介绍了PHP使用file_get_content设置头信息的方法,结合实例形式对比分析了PHP使用fopen及file_get_contents设置及获取头信息的相关技巧,需要的朋友可以参考下
    2016-02-02
  • php中json_decode()和json_encode()的使用方法

    php中json_decode()和json_encode()的使用方法

    json_decode对JSON格式的字符串进行编码而json_encode对变量进行 JSON 编码,需要的朋友可以参考下
    2012-06-06
  • php中cookie的作用域

    php中cookie的作用域

    注意cookie的作用域:
    2008-03-03
  • php中时间轴开发(刚刚、5分钟前、昨天10:23等)

    php中时间轴开发(刚刚、5分钟前、昨天10:23等)

    php中时间轴开发,即显示为“刚刚”、“5分钟前”、“昨天10:23”等
    2011-10-10
  • 调试PHP程序的多种方法介绍

    调试PHP程序的多种方法介绍

    这篇文章主要介绍了调试PHP程序的多种方法介绍,本文讲解了PHP自带的调试功能、引进调试工具、调试业务逻辑错误、调试非功能性的错误等内容,需要的朋友可以参考下
    2014-11-11
  • php数组保存文本与文本反编成数组实例

    php数组保存文本与文本反编成数组实例

    这篇文章主要介绍了php数组保存文本与文本反编成数组的方法,通过两个自定义函数string2array与array2string实例展示了php数组保存文本与文本反编成数组的实现方法,具有不错的参考借鉴价值,需要的朋友可以参考下
    2014-11-11

最新评论