Smarty(和其他 tpl ngins):assign 和assign_by_ref [英] Smarty (and other tpl ngins): assign and assign_by_ref

查看:75
本文介绍了Smarty(和其他 tpl ngins):assign 和assign_by_ref的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这不仅仅是关于 Smarty,但我猜大多数模板引擎都分配了变量.这与其说是实践问题,不如说是一个理论问题.我没有用例.

This is not just about Smarty, but I guess most template engines that have variables assigned. It's more a theoretical question, than a practical. I have no use case.

当您将一个大数组 $a 分配给另一个变量 $b 时,PHP 中会发生什么?PHP复制数组?也许,只是也许,它在内部创建了一个指针.那么当你稍微改变 $a 会发生什么?$b 不应更改,因为没有使用 & 来创建 $b.PHP 是否只是将内存使用量增加了一倍?

What happens in PHP when you assign a big array $a to another variable $b? PHP copies the array? Maybe, just maybe, internally it creates a pointer. Then what happens when you alter $a slightly? $b shouldn't be changed, because no & was used to create $b. Did PHP just double the memory usage??

更具体地说:当您将控制器 ($a) 中的大数组分配给模板引擎 ($tpl->vars['a']) 时会发生什么>) 并在视图中使用(extract$a)?PHP 的内存增加了三倍吗??

More specifically: What happens when you assign a big array from you Controller ($a) to your template engine ($tpl->vars['a']) and to use in the view (extract to $a)? Did PHP's memory just triple??

现在如果我通过引用分配所有变量会发生什么?我很酷,我认为能够将数组更改回控制器(无论如何我不会回到那里).如果变量在模板引擎中发生变化,也没关系 ($tpl->vars['a']).

Now what happens if I assign all my variables by reference? I'm cool with my view being able to alter the array back into the Controller (I won't be coming back there anyway). It's also fine if the variable changes within the templat engine ($tpl->vars['a']).

通过引用分配所有变量对内存更好吗?性能更好?如果是这样:是否有可能出现奇怪的、不需要的副作用?

Is assigning all vars by reference better for memory? Better for performance? If so: any chances of strange, unwanted side effects?

因为人们喜欢代码而不是故事:

Because people like code and not stories:

// copies
$a = array( ... );
$tpl->assign('a', $a); // creates a copy (?) in $tpl->vars['a']

// pointer / by ref
$a = array( ... );
$tpl->assign_by_ref('a', $a); // creates a pointer in $tpl->vars['a'] because:

function assign_by_ref( $name, &$var ) {
  $this->vars[$name] = $var; // voila pointer?
}

我很确定 PHP 不介意大数组、副本和克隆,但在性能和内存方面:哪个更好"?

I'm pretty sure PHP doesn't mind big arrays and copies and clones, but performance and memory wise: which's 'better'?

编辑
对于对象,所有这些都无关紧要.对象总是通过引用自动分配.由于物体很热,也许这是一个过时的问题,但我很好很好奇.

更新
所以 PHP 使用 copy on write...喜欢它.对象始终是指针.当您:

UPDATE
So PHP uses copy on write... Love it. And objects are always pointers. What happens when you:

$a = new BigObject;
$b = $a; // pointer, right?
$b->updateSomethingInternally(); // $b is now changed > what about $a?

这是否触发了写时复制?还是 $a 和 $b 仍然相同(就像在 === 中一样)?

Did this trigger the copy-on-write? Or are $a and $b still identical (like in ===)?

编辑
我是否可以得出结论,仅仅为了节省内存而通过 ref 分配真的不值得?PHP 本身就足够聪明?

edit
Could I conclude that assigning by ref is really not worth it just to spare memory? PHP in itself is smart enough?

编辑
复制、克隆、by-ref 等有趣的可视化:http://www.phpinsider.com/download/PHP5RefsExplained.pdf

推荐答案

PHP 使用了一种称为写时复制的概念.IE.如果你只是做一个 $a = $b PHP 不会将 $b 的整个值复制到 $a.它只会创建某种指针.(更准确地说,$a$b 将指向同一个 zval,并且它的 refcount 将增加.)

PHP uses a concept called copy on write. I.e. if you just do a $a = $b PHP will not copy the whole value of $b to $a. It will just create some kind of a pointer. (To be more precise both $a and $b will point to the same zval and it's refcount will be increased.)

现在,如果 $a$b 被修改,该值显然不能再共享,必须复制.

Now, if either $a or $b were modified the value obviously can't be shared anymore and must be copied.

因此,除非您不修改模板代码中的数组,否则不会进行复制.

So, unless you aren't modifying the array in your template code, no copying will be done.

一些进一步的说明:

  • 当心试图通过盲目插入引用来优化您的代码.通常,它们会产生与您预期相反的效果.解释原因的示例:

  • Beware of trying to optimize your code by blindly inserting references. Often they will have an effect contrary to what you expect. Example to explain why:

$a = SOMETHING_BIG; // $a points to a zval with refcount 1 and is_ref 0
$b = $a;            // $a and $b both point to a zval with refcount 2 and is_ref 0
$c =& $a;           // Now we have a problem: $c can't just point to the same zval
                    // anymore, because that zval has is_ref to 0, but we need one
                    // with is_ref 1. So The zval gets copied. You now have $b
                    // pointing to one zval with refcount 1 and is_ref 0 and $a and
                    // $c pointing to another one with refcount 2 and is_ref 1

所以实际上发生了与您想要的相反的事情.您实际上是在分配额外的内存,而不是节省内存.通常很难判断添加引用是否会使它变得更好或更糟,因为通常很难跟踪指向一个 zval 的所有不同变量(这通常并不像看起来那么容易,只需看看 debug_zval_dump 函数.因此,实际上,唯一安全的方法是了解引用是否对性能有益与否,实际上是对两种变体进行分析.

So the contrary to what you wanted actually happened. Instead of saving memory you are actually allocating additional. It's often hard to judge whether adding a reference will make it better or worse because it's often hard to trace all different variables pointing to one zval (it's often not as easy as it looks, just have a look at the examples of the debug_zval_dump function. So, really, the only safe way to know, whether a reference is good for performance or not, is to actually profile both variants.

这只是对该主题的简短介绍.您可以在 博客中找到对该主题的更深入分析Sara Golemon 的帖子,标题是你被骗了".

This was just a short introduction to the topic. You can find a more in-depth analysis of the topic in a blog post by Sara Golemon with the porvoking title "You're being lied to".

这篇关于Smarty(和其他 tpl ngins):assign 和assign_by_ref的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆