Замыкания или create_function в PHP - PullRequest
3 голосов
/ 26 июня 2011

Я принял решение использовать замыкания для своих обратных вызовов вместо create_function и, таким образом, поддерживать только PHP> 5.3 в основном из-за повышенной отладки, а также потому, что я предположил (что они говорят о предположении?), Чтоиздержки компиляции create_function на лету в моей ситуации, вероятно, компенсируют любые дополнительные сравнения и такие, которые должны были быть сделаны внутри функции.

Это вполне может иметь место (длямое приложение) и требуется дальнейшее тестирование, но меня заинтересовал вывод этого (очень) простого теста, который показывает, что метод create_function работает более чем в два раза быстрее, чем замыкание, когда он может удалить только четыре условия (и concats)).Очевидно, что в моем тестовом случае дополнительная обработка не выполняется, и именно здесь большая часть скорости будет получена или потеряна, но в случае, когда у вас мало дополнительной обработки, но много условий (которые могут быть удалены), иобратный вызов вызывается достаточно раз, и я начал думать, что может быть лучше использовать create_function.

Однако, с очевидным сходством между create_function и eval, я опасаюсь этого.

Итак, главный вопрос в том, чем отличаются анонимные функции, созданные с помощью create_function, от функций замыканий?

Несколько конкретных вопросов, о которых я думаю, будут ли create_function работать даже при отключенной функциональности eval?И я уверен, что где-то недавно читал, что 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();

Ответы [ 2 ]

6 голосов
/ 26 июня 2011

Конструкция function() {..} является анонимной функцией, и эта функция часто реализуется вместе с замыканиями .Ни create_function, ни анонимные функции не загрязняют глобальное пространство имен.

Поскольку анонимные функции могут обращаться к окружающим переменным (часть замыкания), теоретически они могут быть немного медленнее.С другой стороны, если вы используете кэширование байт-кода (а если нет, то, очевидно, вас не беспокоит производительность), я ожидаю, что издержки «компиляции» анонимных функций будут немного медленнее.

Однако крайне маловероятно, что разница между анонимными функциями и create_function является источником проблем с производительностью.Поэтому я бы выбрал более читабельную форму анонимной функции, если вам так повезло иметь целевую платформу с php> 5.3.

2 голосов
/ 19 декабря 2012

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
}

тогда как с анонимными функциями этого не произойдет (закрытие будет сборкой мусора).

...