免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 10493 | 回复: 28
打印 上一主题 下一主题

PHP数组赋值是不是“写时拷贝”? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2006-12-25 20:30 |只看该作者 |倒序浏览
一些有关PHP执行效率的问题想请教懂得PHP内核原理的人。

当把一个数组$A赋值给一个变量$B:$B=$A,对PHP内核来说,是立即把$A的数据结构完整地复制给$B,还是先在$B上建立一个对于$A的引用,只有当把新的元素写入$B时,这时$A的结构才被复制给$B,同时$B的结构被修改,也就是类似于操作系统内核复制进程内存页面时所采用的“写时拷贝”技术。当把数组以值传递给函数时:f($A)是不是也经历同样的过程,只有当$A被修改时,$A的结构才会被复制,否则将在函数内共享函数外的数组变量。

谁能指出PHP源代码中与之相关的代码。

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
2 [报告]
发表于 2006-12-25 22:22 |只看该作者
简单赋值只是引用,如果改变了一个“副本”的内容,才会实际拷贝。

论坛徽章:
0
3 [报告]
发表于 2006-12-26 03:12 |只看该作者
楼主的意思是对的
但是这样的例子还真不好写

论坛徽章:
0
4 [报告]
发表于 2006-12-26 09:37 |只看该作者
php的赋值不是写时copy,,,它就是一个简单的copy。

写了个小东西,,帮你理解。

<?php
        $a = '123';
        $b = & $a;
        echo $b;
        echo "<br>";
        $a = '98';
        echo $b;
        echo "<br>";
        unset($a);
        echo $b;

?>

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
5 [报告]
发表于 2006-12-26 10:02 |只看该作者
原帖由 james.liu 于 2006-12-26 09:37 发表
php的赋值不是写时copy,,,它就是一个简单的copy。

写了个小东西,,帮你理解。

<?php
        $a = '123';
        $b = & $a;
        echo $b;
        echo "<br>";
        $a = '98';
        echo $b;
        echo & ...


  这个问题,你没有深入研究,没有实践,不要妄下结论。

  我们用一段非常简单的代码,来测试即可:

  1. php -r "echo(1);$a=range(0,1234567);sleep(5);echo(2);$b=$a
  2. ;sleep(5);echo(3);$b[0]=-1;sleep(5);"
复制代码

  此段代码的测试方法:
1. 打开内存监控软件(如Windows的任务管理器的性能页、Unix系统的top或者GUI的系统监控软件)
2. 使用php/cli执行此代码,Windows下面使用cli版本的php
3. 在显示1、2、3,分别注意此时的内存占用。

  实际结果:
显示1:内存明显使用增加
显示2:内存几无增加
显示3:同1,且增加大小与1相似。

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
6 [报告]
发表于 2006-12-26 10:13 |只看该作者
原帖由 james.liu 于 2006-12-26 09:37 发表
php的赋值不是写时copy,,,它就是一个简单的copy。

写了个小东西,,帮你理解。

<?php
        $a = '123';
        $b = & $a;
        echo $b;
        echo "<br>";
        $a = '98';
        echo $b;
        echo & ...


  另外,楼主说的是数组赋值,而不是引用,引用的话是针对同一数据空间操作的。

另外测试:

  1. php -r "echo(1);$a=str_repeat(' ',123456789);sleep(5);echo
  2. (2);$b=$a;sleep(5);echo(3);$b.=' ';sleep(5);"
复制代码


  测试结果与前面相同。

论坛徽章:
0
7 [报告]
发表于 2006-12-26 10:13 |只看该作者
这个问题我前一段时间也遇到了,当时觉的头晕晕的,搞不清除什么时候是引用什么时候是copy.
我也查看了手册,手册讲的还是比较全面的不过没有给出全面的例子.
不过我有一个感觉:手册的观点是建立在内部机制的角度,不是我们脚本的角度
我测试的结果是:
数组(类成员数组)赋值给其它变量的时候是copy.
但是如果你在赋值的时候使用了&--就是引用了(废话),
关键是当你把引用后的变量当作函数的参数传递时,就是引用了,并且这个引用会继承下去
也就是引用具有全局的引用生命周期.

总结成一句话就是:

数组赋值是copy,引用传参永继承.

如果不对请大家批......
当然我的出发角度是脚本的角度,没有考虑乔帮主说的内存使用等那么深层的问题

[ 本帖最后由 achun.shx 于 2006-12-26 10:16 编辑 ]

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
8 [报告]
发表于 2006-12-26 10:15 |只看该作者
关于PHP写时拷贝的一些说明,可以看:
http://cn.php.net/debug_zval_dump

When a variable has a single reference (as did $var1 before it was used as an argument to debug_zval_dump()), PHP's engine optimizes the manner in which it is passed to a function. Internally, PHP treats $var1 like a reference (in that the refcount is increased for the scope of this function), with the caveat that if the passed reference happens to be written to, a copy is made, but only at the moment of writing. This is known as "copy on write."

So, if debug_zval_dump() happened to write to its sole parameter (and it doesn't), then a copy would be made. Until then, the parameter remains a reference, causing the refcount to be incremented to 2 for the scope of the function call.

论坛徽章:
0
9 [报告]
发表于 2006-12-26 10:31 |只看该作者
开眼界了

前两天也看了一点php的源码,发现strlen也是作了优化,不必象c那样,每次都从字符串前向后做循环检查是否为'\0'。

所以,字符串"abc\0abc"这种二进制字符串不会出错。

论坛徽章:
1
技术图书徽章
日期:2013-12-05 23:25:45
10 [报告]
发表于 2006-12-26 10:35 |只看该作者
原帖由 achun.shx 于 2006-12-26 10:13 发表
这个问题我前一段时间也遇到了,当时觉的头晕晕的,搞不清除什么时候是引用什么时候是copy.
我也查看了手册,手册讲的还是比较全面的不过没有给出全面的例子.
不过我有一个感觉:手册的观点是建立在内部机制的角度, ...


  从内存入手,只是一个很直观的检查我们相法的一个方法。

  另外,我给出的这个手册的地方,是进行PHP扩展需要了解的一些知识,这个肯定是要从内部机制入手的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP