2011-06-26 25 views
3

我已经决定使用闭包而不是create_function,因此只支持PHP> 5.3,这主要是由于增加了可调试性,也是因为我认为(他们对假设的看法是什么? )在我的情况下,编译create_function的开销可能会抵销任何额外的比较,并且必须在函数中进行。 (这对我的应用程序而言)并且需要进一步的测试,但是我对这个(非常)简单的测试的输出感兴趣,它显示了create_function方法的速度是当它只能删除四个条件(连接)时关闭。很明显,在我的测试用例中没有额外的处理,这就是大部分速度会增加或者丢失的地方,但是如果你只有很少的额外处理,但是很多条件(可以被删除)和回调被称为足够多的时间,我开始认为使用create_function可能会更好。PHP中的闭包或create_function

但是,由于create_functioneval之间有明显的相似性,我很谨慎。

所以主要问题是用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(); 
+0

它应该很容易测试在哪个名称空间'create_function' ..创建函数.. :) –

+0

我会去封闭也。就速度而言,也许你应该用真实世界的案例来测试它。我不知道为什么这个应该慢得多,但我会采取'打'。另外,APC在这种情况下是否有所作为?闭包是否缓存在操作码中?它也可能有所作为。 – Arend

+0

将它们分开。这个问题已经很长了。 – phihag

回答

6

的结构function() {..}是一个匿名函数,这个功能经常与closures一起实施。 create_function和匿名函数都不会污染全局名称空间。

由于匿名函数可以访问周围的变量(闭包部分),理论上它们可以稍微慢一些。另一方面,如果你使用字节码缓存(如果你不是,你显然不关心性能),我期望匿名函数的“编译”开销稍微慢一些。

但是,匿名函数和create_function之间的差异是造成性能问题的根源的可能性极小。因此,如果你非常幸运地拥有一个php> 5.3的目标平台,我会选择一个更具可读性的匿名函数。

+1

那么,这取决于你的意思是“污染全球命名空间”。 'create_function'确实创建了一个全局函数,但是它的名字不会和你用于函数的名字冲突。 – newacct

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 
} 

而用匿名函数,这不会发生(关闭将被垃圾收集)。