В 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
);
Теперь я полагаю, что последняя форма оценивается механизмом PHP один раз во время компиляции, в то время как другая форма может оцениваться во время выполнения, возможно, для каждого вызова, что означает, что использование замыкания было бы гораздо более эффективным для большого количества вызовов. Это предположение верно?
Я выполнил функцию несколькими различными способами и записал время выполнения.
Похоже, что использование строковой ссылки на обычную функцию намного эффективнее.
Резюме
Нормальное определение функции и вызов
$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";
Средний: 3.208938837
Лямбда-определение и вызов внутри цикла
$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";
Среднее: 10.32323852
Лямбда-определение вне цикла
$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";
Средний балл: 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";
Среднее: 13.72040915
Лямбда-определение и внешний цикл и 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";
Средний: 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";
Среднее: 4.001193714
Лямбда-определение вне цикла с помощью array_map ()
$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";
Средний балл: 10,1116962
Других решений пока нет …