为什么在 call_user_func_array() 之前使用 switch 语句
Why is a switch statement used before call_user_func_array()
我一直在查看 laravel 源代码,我在 callStatic 魔术方法中偶然发现了这个:
switch (count($args)) {
case 0:
return $instance->$method();
case 1:
return $instance->$method($args[0]);
case 2:
return $instance->$method($args[0], $args[1]);
case 3:
return $instance->$method($args[0], $args[1], $args[2]);
case 4:
return $instance->$method($args[0], $args[1], $args[2], $args[3]);
default:
return call_user_func_array([$instance, $method], $args);
}
为什么先用switch语句再用call_user_func_array()?
因为克莱夫在评论中有 ;这是因为性能问题。
call_user_func_array()
因其性能问题而广为人知。正如一些基准显示的那样,它甚至比它的姊妹函数 call_user_func()
慢 10-20%。
这是基准测试的结果 运行 比较直接调用与动态调用与通过 call_user_func*
函数调用的性能:
Dynamic function calls are slightly slower than straight calls (the former have an extra interpretive layer to determine the function to call
call_user_func()
is about 50% slower, and call_user_func_array()
is about 100% slower than a straight function call.
Static and regular method calls are roughly equivalent to function calls
call_user_func()
on method calls is typically slower than call_user_func_array()
, and the faster operation usually takes at least twice the execution time of a straight call.
— Matthew Weier O'Phinney
Paul M. Jones,另一位著名的 PHP 开发人员,也是 运行 完全相同主题的基准,并得出结论:
So native calls to htmlentities()
are twice as fast as doing effectively the same thing via call_user_func()
with an object method, and using call_user_func_array()
is 10-20% slower than using call_user_func()
...
Clearly, PHP has to do a lot more work behind the scenes to map the variables to objects and parameters when using call_user_func_array()
.
— Paul M. Jones
参数解包
最后一件事;从 PHP 5.6 开始,使用参数解包运算符 advent(又名 spread、splat 或 scatter 运算符),您可以安全地将该代码重写为:
$instance->$method(...$args);
Furthermore call_user_func_array
has a rather large performance impact. If a large number of calls go through it, this can make a significant difference. For this reason, projects like Laravel and Drupal often replace particularly common call_user_func_array
calls with a switch statements.
The ...
argument unpacking syntax is about 3.5 to 4 times faster than call_user_func_args
. This solves the performance issue. Benchmark code and results.
我一直在查看 laravel 源代码,我在 callStatic 魔术方法中偶然发现了这个:
switch (count($args)) {
case 0:
return $instance->$method();
case 1:
return $instance->$method($args[0]);
case 2:
return $instance->$method($args[0], $args[1]);
case 3:
return $instance->$method($args[0], $args[1], $args[2]);
case 4:
return $instance->$method($args[0], $args[1], $args[2], $args[3]);
default:
return call_user_func_array([$instance, $method], $args);
}
为什么先用switch语句再用call_user_func_array()?
因为克莱夫在评论中有
call_user_func_array()
因其性能问题而广为人知。正如一些基准显示的那样,它甚至比它的姊妹函数 call_user_func()
慢 10-20%。
这是基准测试的结果 运行 比较直接调用与动态调用与通过 call_user_func*
函数调用的性能:
Dynamic function calls are slightly slower than straight calls (the former have an extra interpretive layer to determine the function to call
call_user_func()
is about 50% slower, andcall_user_func_array()
is about 100% slower than a straight function call.Static and regular method calls are roughly equivalent to function calls
call_user_func()
on method calls is typically slower thancall_user_func_array()
, and the faster operation usually takes at least twice the execution time of a straight call.
— Matthew Weier O'Phinney
Paul M. Jones,另一位著名的 PHP 开发人员,也是 运行 完全相同主题的基准,并得出结论:
So native calls to
htmlentities()
are twice as fast as doing effectively the same thing viacall_user_func()
with an object method, and usingcall_user_func_array()
is 10-20% slower than usingcall_user_func()
...Clearly, PHP has to do a lot more work behind the scenes to map the variables to objects and parameters when using
call_user_func_array()
.
— Paul M. Jones
参数解包
最后一件事;从 PHP 5.6 开始,使用参数解包运算符 advent(又名 spread、splat 或 scatter 运算符),您可以安全地将该代码重写为:
$instance->$method(...$args);
Furthermore
call_user_func_array
has a rather large performance impact. If a large number of calls go through it, this can make a significant difference. For this reason, projects like Laravel and Drupal often replace particularly commoncall_user_func_array
calls with a switch statements.The
...
argument unpacking syntax is about 3.5 to 4 times faster thancall_user_func_args
. This solves the performance issue. Benchmark code and results.