PHP 中的闭包或 create_function
Posted
技术标签:
【中文标题】PHP 中的闭包或 create_function【英文标题】:Closures or create_function in PHP 【发布时间】:2011-09-23 01:00:21 【问题描述】:我决定在我的回调中使用闭包而不是 create_function
,因此只支持 php > 5.3,主要是因为增加了可调试性,也因为我假设(他们对假设有什么看法?)在我的情况下,create_function
的即时编译的开销可能会抵消任何额外的比较,并且必须在函数中进行。
情况可能仍然如此(对于我的应用程序)并且需要进一步测试,但我对这个(非常)简单测试的输出很感兴趣,它表明 create_function
方法的速度是当它只能删除四个条件(和连接)时的闭包。显然,在我的测试用例中没有进行额外的处理,这就是大部分速度将获得或损失的地方,但是在您几乎没有额外处理但有很多条件(可以删除)和回调被调用了足够多次我开始认为使用create_function
可能会更好。
但是create_function
和eval
之间有明显的相似之处,我对此持谨慎态度。
所以主要问题是使用create_function
创建的匿名函数与闭包创建的匿名函数有什么区别?
我正在考虑的几个具体问题是,当eval
功能被禁用时,create_function
是否还能工作?而且,我确定我最近在某处读到 create_function
函数即使声明为内部函数也会污染全局(或类)命名空间,但闭包不会。我现在找不到对此的参考,但这些陈述中的一个或两个都是真的吗?
这是我跑的小测试:
<?php
function foo($a=true, $b=true, $c=true, $d=true)
$inner1 = create_function(
'',
'$r = \''.($a ? 'a' : '').
($b ? 'b' : '').
($c ? 'c' : '').
($d ? 'd' : '').'\';
return $r;'
);
$inner2 = function() use ($a, $b, $c, $d)
$r = '';
if($a) $r .= 'a';
if($b) $r .= 'b';
if($c) $r .= 'c';
if($d) $r .= 'd'; ;
return $r;
;
$time = microtime(true);
for ($x=0; $x<99999; ++$x)
$i1out = $inner1();
echo '1:'.(microtime(true)-$time).'<br>';
$time = microtime(true);
for ($x=0; $x<99999; ++$x)
$i2out = $inner2();
echo '2:'.(microtime(true)-$time).'<br>';
echo var_dump($i1out===$i2out).'<br>';
foo();
【问题讨论】:
应该很容易测试在哪个命名空间create_function
.. 创建函数.. :)
我也会去关闭。在速度方面,也许你应该用真实的案例场景来测试它。我不确定为什么那个应该慢得多,但我会接受“打击”。此外,APC 在这种情况下是否有所作为?闭包是否缓存在操作码中?它也可能会有所作为。
把它们分开。这个问题已经……很长了。
@phihag 你是对的,它很长,所以它完成了。
【参考方案1】:
function() ..
的构造是一个匿名函数,这个特性经常与closures 一起实现。 create_function
和匿名函数都不会污染全局命名空间。
由于匿名函数可以访问周围的变量(闭包部分),理论上它们可以稍微慢一些。另一方面,如果你使用字节码缓存(如果你不使用,你显然不关心性能),我预计匿名函数的“编译”开销会稍微慢一些。
但是,匿名函数和create_function
之间的差异极不可能是性能问题的根源。因此,如果您有幸拥有 php>5.3 的目标平台,我会选择更易读的匿名函数形式。
【讨论】:
嗯,这取决于您所说的“污染全局命名空间”是什么意思。create_function
确实创建了一个全局函数,但它的名称不会与您用于函数的名称冲突。【参考方案2】:
create_function
创建一个全局函数,该函数对程序的其余部分持续存在。 create_function
只返回函数名(一个字符串),因此不知道您是否仍然可以访问以某种方式存储在某处的该名称。因此,它不能被“垃圾收集”,即使您不再有权访问该名称。
这意味着一个大问题是如果你使用create_function
创建了很多函数,它会导致你的程序内存不足:
for ($i = 0; $i < 1000000; $i++)
$f = create_function('', '');
// do stuff
// don't use $f anywhere after this point
而对于匿名函数,这不会发生(闭包将被垃圾收集)。
【讨论】:
以上是关于PHP 中的闭包或 create_function的主要内容,如果未能解决你的问题,请参考以下文章
带有字符串键或嵌套引号的数组到 php 中的 lambda 函数中