PHP Laravel Facade __callStatic argument list

Not sure how to put it right. While delving into the Laravel 4 classes to see how Facades work, I came across this:

Illuminate\Support\Facades\ Facades.php@ __callStatic public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); 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(array($instance, $method), $args); } } 

Now, from what I can say, this method calls any given class method, references Facade, and passes arguments. I could be wrong, but this is my understanding so far.

The part that really bothers me is the switch.

Why are cases from 0 to 4 needed if the default case will work independently.

Even if case 0 makes sense, if there is no argument, why is there case 1-4, and not just continue case 10, for example. Is there a reasonable argument for this, or is it just a case of premature optimization?

+6
source share
3 answers

I suspect this is micro-optimization. I also suspect that most of these static calls to facades will require 4 or fewer arguments, in which case most of the static calls will not skip to the default case.

I managed to find this quote submitted by the user in the entry on call_user_func_array from "noone at example dot com":

For those of you who have to consider performance: a call is required three times as much as through a direct operator, so whenever possible, avoid this method, it is a wise idea to do this.

Running a very simple test also seems to confirm its validity. In the results, 1 calls the method directly in the instance, 2 calls the name of the method in the instance, and 3 uses call_user_func_array , and the output time in seconds. The number of iterations for each approach is 1,000,000.

 $ php test.php (1) total: 0.51281404495239 (2) total: 0.51285219192505 (3) total: 1.1298811435699 $ php test.php (1) total: 0.49811697006226 (2) total: 0.5209321975708 (3) total: 1.1204349994659 $ php test.php (1) total: 0.48825788497925 (2) total: 0.51465392112732 (3) total: 1.156769990921 

The above results show that avoiding call_user_func_array can speed up calls to static facade methods by at least about 2 times, unless the static method has more than 4 arguments.

As for why the cutoff value is selected from 4 parameters, only Taylor knows. This method has been (basically) unchanged since Laravel 4.0 first committed , and I suspect it is somewhat arbitrary.

+4
source

You are right, call call_user_func_array(); works fine without using a switch . But , in accordance with this standard , it seems very slow:

 function html($value) { return htmlentities($value); } name : diff : total : description native : 0.614219 : 0.613295 : htmlentities($value) literal_func : 0.745537 : 1.346594 : html($value) variable_func : 0.826048 : 2.162376 : $func($value) literal_method : 0.957708 : 3.127519 : $object->html($value) variable_method : 0.840837 : 3.970290 : $object->$func($value) call_func : 1.006599 : 4.993930 : call_user_func($func, $value) call_object : 1.193323 : 6.215677 : call_user_func((array($object, $func), $value) cufa_func : 1.232891 : 7.320287 : call_user_func_array($func, array($value)) cufa_object : 1.309725 : 8.769755 : call_user_func_array((array($object, $func), array($value) 

So basically this becomes a problem when you use call_user_func_array() many times (this is the case in Laravel). This is why they use the switch .

+4
source

Because $instance->$method() faster than call_user_func_array .

Considering that this piece of code can be called many times in one cycle, it makes sense to optimize it as much as possible.

+3
source

Source: https://habr.com/ru/post/977413/


All Articles