【问题标题】:Closures or create_function in PHPPHP 中的闭包或 create_function
【发布时间】:2011-09-23 01:00:21
【问题描述】:

我决定在我的回调中使用闭包而不是 create_function,因此只支持 PHP > 5.3,主要是因为增加了可调试性,也因为我假设(他们对假设有什么看法?)在我的情况下,create_function 的即时编译的开销可能会抵消任何额外的比较,并且必须在函数中进行。

情况可能仍然如此(对于我的应用程序)并且需要进一步测试,但我对这个(非常)简单测试的输出很感兴趣,它表明 create_function 方法的速度是当它只能删除四个条件(和连接)时的闭包。显然,在我的测试用例中没有进行额外的处理,这就是大部分速度将获得或损失的地方,但是在您几乎没有额外处理但有很多条件(可以删除)和回调被调用了足够多次我开始认为使用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();

【问题讨论】:

  • 应该很容易测试在哪个命名空间create_function.. 创建函数.. :)
  • 我也会去关闭。在速度方面,也许你应该用真实的案例场景来测试它。我不确定为什么那个应该慢得多,但我会接受“打击”。此外,APC 在这种情况下是否有所作为?闭包是否缓存在操作码中?它也可能会有所作为。
  • 把它们分开。这个问题已经……很长了。
  • @phihag 你是对的,它很长,所以它完成了。

标签: php callback closures anonymous-function


【解决方案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
}

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-09-23
    • 1970-01-01
    • 2018-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多