在PHP中,将lambda表达式用于可调用而不是字符串(或数组)是否更有效?

Han*_*etz 6 php arrays lambda callable

在PHP中,某些函数将"可调用"作为参数,这意味着您可以指定要在某一点执行的函数.一个例子是array_map.

PHP允许您以多种方式指定可调用对象,例如:

// as a string:
$lowerCaseStrings = array_map('strtolower', $arrayOfStrings);

// object methods as an array
// (this could be done with DateTime directly, of course):
class DateFactory {
    private $format;

    public function __construct($format) {
        $this->format = $format;
    }

    public function newDate($dateString) {
        return DateTime::createFromFormat($this->format, $dateString); 
    }
}

$factory = new DateFactory('Y-m-d');
$dates = array_map(array($factory, 'newDate'), $arrayOfDateStrings);

// as a lambda expression / closure:
$dates = array_map(
        function ($dateString) {
            return DateTime::createFromFormat('Y-m-d', $dateString);
        },
        $arrayOfDateStrings
    );
Run Code Online (Sandbox Code Playgroud)

现在,我认为后一种形式在编译期间由PHP引擎进行一次评估,而另一种形式可能在运行时期间进行评估,可能是针对每次调用,这意味着使用闭包对于大量调用会更有效.这个假设是否正确?

小智 3

我用几种不同的方式执行了一个函数并记录了运行时间。看起来使用对常规函数的字符串引用效率更高。

概括

  1. 使用 array_map() 的普通函数定义:4.001193714
  2. 使用 array_map() 的 Lambda 定义外部循环:10.1116962
  3. 正常函数定义和调用:3.208938837
  4. 循环内的 Lambda 定义和调用:10.32323852
  5. 循环外的 Lambda 定义:9.616424465
  6. 普通函数定义和call_user_func():13.72040915
  7. 循环外的 Lambda 定义和 call_user_func(): 19.98814855

正常的函数定义和调用

$start_time = microtime(true);

function run_this() {
    // Empty function
}

for($i = 0; $i < 5000000; $i++) {
    run_this();
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 3.1148610115051
  2. 3.0175619125366
  3. 3.5064949989319
  4. 3.3637712001801
  5. 3.0420050621033

平均:3.208938837

Lambda 定义和循环内调用

$start_time = microtime(true);

for($i = 0; $i < 5000000; $i++) {
    $run_this = function () {
        // Empty function
    };
    $run_this();
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 9.857855797
  2. 10.07680297
  3. 10.35639596
  4. 10.51450491
  5. 10.81063294

平均值:10.32323852

循环外的 Lambda 定义

$start_time = microtime(true);

$run_this = function () {
    // Empty function
};

for($i = 0; $i < 5000000; $i++) {
    $run_this();
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 9.098902941
  2. 9.580584049
  3. 9.370799065
  4. 9.90805316
  5. 10.12378311

平均值:9.616424465

普通函数定义和call_user_func()

$start_time = microtime(true);

function run_this () {
    // Empty function
};

for($i = 0; $i < 5000000; $i++) {
    call_user_func('run_this');
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 12.80056691
  2. 13.47905684
  3. 14.51880193
  4. 13.79459596
  5. 14.00902414

平均:13.72040915

Lambda 定义和外部循环以及 call_user_func()

$start_time = microtime(true);

$run_this = function () {
    // Empty function
};

for($i = 0; $i < 5000000; $i++) {
    call_user_func($run_this);
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 18.99004483
  2. 20.08601403
  3. 20.52800584
  4. 20.16949892
  5. 20.16717911

平均:19.98814855

使用 array_map() 的普通函数定义

$arr = array_pad([], 5000, 0);

$start_time = microtime(true);

function run_this () {
    // Empty function
};

for($i = 0; $i < 1000; $i++) {
    array_map('run_this', $arr);
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 3.727953911
  2. 4.213405848
  3. 4.068621874
  4. 4.180392027
  5. 3.815594912

平均值:4.001193714

使用 array_map() 在循环外定义 Lambda

$arr = array_pad([], 5000, 0);

$start_time = microtime(true);

$run_this = function () {
    // Empty function
};

for($i = 0; $i < 1000; $i++) {
    array_map($run_this, $arr);
}

print "Execution time: " . (microtime(true) - $start_time) . "\n";
Run Code Online (Sandbox Code Playgroud)
  1. 9.418456793
  2. 10.07496095
  3. 10.1241622
  4. 10.74794412
  5. 10.19295692

平均值:10.1116962