Smarty(和其他tpl ngins):分配和分配_by_ref
这不仅仅是 Smarty 的问题,我猜大多数模板引擎都分配了变量。这更多的是一个理论问题,而不是一个实践问题。我没有用例。
当您将一个大数组 $a
分配给另一个变量 $b
时,PHP 中会发生什么? PHP 复制数组?也许,只是也许,它在内部创建了一个指针。那么当你稍微改变 $a
时会发生什么? $b
不应更改,因为没有使用 &
来创建 $b
。 PHP 是否只是使内存使用量增加了一倍?
更具体地说:当您将控制器 ($a
) 中的一个大数组分配给模板引擎 ($tpl->vars['a']
) 并在视图中使用(提取
到$a
)? PHP 的内存增加了三倍吗?
现在,如果我通过引用分配所有变量会发生什么?我很高兴我的观点能够将阵列更改回控制器(无论如何我都不会回到那里)。如果变量在模板引擎内发生变化也没关系($tpl->vars['a']
)。
通过引用分配所有变量是否更适合内存?性能更好?如果是这样:是否有可能出现奇怪的、不需要的副作用?
因为人们喜欢代码而不是故事:
// 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 不介意大数组、副本和克隆,但在性能和内存方面:哪个“更好”?
编辑
对于对象来说,这一切都不重要。对象总是通过引用自动分配。由于物体很热,也许这是一个过时的问题,但我很好很好奇。
更新
所以 PHP 使用copy on write
...喜欢它。对象始终是指针。当您执行以下操作时会发生什么:
$a = new BigObject;
$b = $a; // pointer, right?
$b->updateSomethingInternally(); // $b is now changed > what about $a?
这是否触发了写时复制?或者 $a 和 $b 仍然相同(就像 ===
中一样)?
编辑
我是否可以得出这样的结论:仅仅为了节省内存而通过 ref 进行分配确实不值得? PHP本身足够聪明吗?
编辑
有趣的复制、克隆、引用等可视化:http://www.phpinsider.com/download /PHP5RefsExplained.pdf
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.
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??
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??
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?
}
I'm pretty sure PHP doesn't mind big arrays and copies and clones, but performance and memory wise: which's 'better'?
edit
For objects, all of this doesn't matter. Objects are always, automatically assigned by reference. And since objects are hot, maybe this is an outdated question, but I am very curious.
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?
Did this trigger the copy-on-write? Or are $a and $b still identical (like in ===
)?
edit
Could I conclude that assigning by ref is really not worth it just to spare memory? PHP in itself is smart enough?
edit
Interesting visualization of copy, clone, by-ref etc: http://www.phpinsider.com/download/PHP5RefsExplained.pdf
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
PHP 使用称为写入时复制的概念。也就是说,如果您只是执行
$a = $b
PHP 不会将$b
的整个值复制到$a
。它只会创建某种指针。 (更准确地说,$a
和$b
将指向相同的 zval,并且它的refcount
将增加。)现在,如果
$a
或$b
被修改,值显然不能再共享,必须复制。因此,除非您不修改模板代码中的数组,否则不会进行任何复制。
一些进一步的注意事项:
谨防尝试通过盲目插入引用来优化代码。通常它们会产生与您预期相反的效果。举例说明原因:
所以实际情况与你想要的相反。您实际上不是在节省内存,而是在分配额外的内存。通常很难判断添加引用是否会使情况变得更好或更糟,因为通常很难跟踪指向一个 zval 的所有不同变量(这通常不像看起来那么容易,只需看一下
debug_zval_dump
函数 因此,实际上,这是了解引用是否有利于性能的唯一安全方法。或不,是实际分析这两种变体。这只是对该主题的简短介绍。您可以在 博客中找到对该主题的更深入分析Sara Golemon 的帖子,标题是“你被骗了”。
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'srefcount
will be increased.)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.
Some further notes:
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:
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.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".
正如其他答案中提到的,PHP 采用写时复制。不过我确实想回答你帖子的这一部分:
这并不完全正确。它们被分配一个指向对象的标识符。
将此与通过引用分配进行对比:
更新
在您的编辑中,您会询问:
因为
$b
现在包含一个标识符,即现在“指向”与$a
相同的对象,所以$a
也会受到影响。从来没有涉及任何对象的复制。As mentioned in other answers, PHP employs copy-on-write. However I do wish to answer this part of your post:
This is not entirely true. They are assigned an identifier which points to an object.
Contrast this with assigning by reference:
Update
In your edit you ask:
Because
$b
now contains an identifier, i.e. now "points" to same object as$a
,$a
is also affected. There was never any copying of objects involved.PHP 在传递数组时使用写时复制,因此在修改数组之前不会使用额外的内存。抱歉,没有链接来支持此声明。
PHP uses copy-on-write when passing arrays around, so no extra memory is used until you modify the array. Sorry, no link to back up this claim.