下载首页 | 资讯中心 | 文章分类 | 最近更新 | 排 行 榜 | 国产软件 | 国外软件 | 绿色软件 | 汉化补丁 | |
文章搜索: 分类 关键字
您的位置:首页编程开发网络编程 → 网管必读 深入探讨PHP中的内存管理问题
网管必读 深入探讨PHP中的内存管理问题
来源:天极yesky 作者: 加入时间:2006-12-8 访问次数:9 [  ]



  这个问题可以借助于zval(它有好几种形式)的第四个成员refcount加以解决。当一个变量被首次创建并赋值时,它的refcount被初始化为1,因为它被假定仅由最初创建它时相应的变量所使用。当你的代码片断开始把helloval赋给$b时,它需要把refcount的值增加为2;这样以来,现在该值被两个变量所引用:

{
 zval *helloval;
 MAKE_STD_ZVAL(helloval);
 ZVAL_STRING(helloval, "Hello World", 1);
 zend_hash_add(EG(active_symbol_table), "a", sizeof("a"),&helloval, sizeof(zval*), NULL);
 ZVAL_ADDREF(helloval);
 zend_hash_add(EG(active_symbol_table), "b", sizeof("b"),&helloval,sizeof(zval*),NULL);
}

  现在,当unset()删除原变量的$a相应的副本时,它就能够从refcount参数中看到,还有另外其他人对该数据感兴趣;因此,它应该只是减少refcount的计数值,然后不再管它。

  六、 写复制(Copy on Write)

  通过refcounting来节约内存的确是不错的主意,但是,当你仅想改变其中一个变量的值时情况会如何呢?为此,请考虑下面的代码片断:

<?php
$a = 1;
$b = $a;
$b += 5;
?>

  通过上面的逻辑流程,你当然知道$a的值仍然等于1,而$b的值最后将是6。并且此时,你还知道,Zend在尽力节省内存-通过使$a和$b都引用相同的zval(见第二行代码)。那么,当执行到第三行并且必须改变$b变量的值时,会发生什么情况呢?

  回答是,Zend要查看refcount的值,并且确保在它的值大于1时对之进行分离。在Zend引擎中,分离是破坏一个引用对的过程,正好与你刚才看到的过程相反:

zval *get_var_and_separate(char *varname, int varname_len TSRMLS_DC)
{
 zval **varval, *varcopy;
 if (zend_hash_find(EG(active_symbol_table),varname, varname_len + 1, (void**)&varval) == FAILURE) {
  /* 变量根本并不存在-失败而导致退出*/
  return NULL;
 }
 if ((*varval)->refcount < 2) {
  /* varname是唯一的实际引用,
  *不需要进行分离
  */
  return *varval;
 }
 /* 否则,再复制一份zval*的值*/
 MAKE_STD_ZVAL(varcopy);
 varcopy = *varval;
 /* 复制任何在zval*内的已分配的结构*/
 zval_copy_ctor(varcopy);
 /*删除旧版本的varname
 *这将减少该过程中varval的refcount的值
 */
 zend_hash_del(EG(active_symbol_table), varname, varname_len + 1);
 /*初始化新创建的值的引用计数,并把它依附到
 * varname变量
 */
 varcopy->refcount = 1;
 varcopy->is_ref = 0;
 zend_hash_add(EG(active_symbol_table), varname, varname_len + 1,&varcopy, sizeof(zval*), NULL);
 /*返回新的zval* */
 return varcopy;
}

  现在,既然引擎有一个仅为变量$b所拥有的zval*(引擎能知道这一点),所以它能够把这个值转换成一个long型值并根据脚本的请求给它增加5。

  七、 写改变(change-on-write)

  引用计数概念的引入还导致了一个新的数据操作可能性,其形式从用户空间脚本管理器看来与"引用"有一定关系。请考虑下列的用户空间代码片断:

<?php
$a = 1;
$b = &$a;
$b += 5;
?>

  在上面的PHP代码中,你能看出$a的值现在为6,尽管它一开始为1并且从未(直接)发生变化。之所以会发生这种情况是因为当引擎开始把$b的值增加5时,它注意到$b是一个对$a的引用并且认为"我可以改变该值而不必分离它,因为我想使所有的引用变量都能看到这一改变"。

  但是,引擎是如何知道的呢?很简单,它只要查看一下zval结构的第四个和最后一个元素(is_ref)即可。这是一个简单的开/关位,它定义了该值是否实际上是一个用户空间风格引用集的一部分。在前面的代码片断中,当执行第一行时,为$a创建的值得到一个refcount为1,还有一个is_ref值为0,因为它仅为一个变量($a)所拥有并且没有其它变量对它产生写引用改变。在第二行,这个值的refcount元素被增加为2,除了这次is_ref元素被置为1之外(因为脚本中包含了一个"&"符号以指示是完全引用)。
上一页 [1] [2] [3] [4] [5] 下一页
评论人 评论内容摘要(共 0 条,查看完整内容) 得分 0 发表时间
 热点文章
·惊爆!《暗黑破坏神3》将对应全平台
·《荣誉勋章:太平洋之战》中文版上市
·MediaShow魅力四射快速制作音乐电子相册
·《花木兰》完美流程攻略
·轻松可爱 最新10大Q版网络游戏推荐
·2006年暑期新宣布免费网络游戏一览
·photoshop制作水晶球中的精灵
·NVIDIA发布Forceware 93.71 WHQL驱动
·经验分享 微软Word2007实用技巧两则
·国内新记录产生 1M super pi运算仅用9秒
 推荐文章
·微软高官爆料:欧盟对Vista哪些功能不安
·在Google Talk上与QQ、MSN好友聊天
·Word使用过程中的常见问题及其解决
·手把手教你内存终极变相“造假”大法
·NVIDIA联手海盗船 推出自动超频内存
·Windows Vista特殊功能介绍:语音识别
·公安机关检验软件样本 流氓软件制造者面临坐牢危..
·比英特尔UMPC还要小 移动PC新品推出
·性感暴力完美结合 御姐武戏X新画面
·盖茨访谈:我就是微软里的兼职员工
WinXP下载基地 版权所有 Copyright© 2006-2008 WWW.WinXpd.COM, All Rights Reserved. 页面维护: WinXP下载基地(WinXP基D)