Last active
November 2, 2015 23:44
-
-
Save krmgns/cd5de6397dd732751fec to your computer and use it in GitHub Desktop.
Simulate PHP (hacked) type hint performance.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| set_error_handler(function($ecode, $emesg, $efile, $eline) { | |
| if (!$ecode || (error_reporting() & $ecode) == 0) { | |
| return; | |
| } | |
| if ($ecode == E_RECOVERABLE_ERROR) { | |
| $pattern = '~^Argument (\d)+ passed to (.+) must be '. | |
| '(?<type>of the type|an instance of) (?<hint>.+), (?<given>.+) given~i'; | |
| if (preg_match($pattern, $emesg, $match)) { | |
| $error = true; | |
| $hint =@ end(explode('\\', strtolower($match['hint']))); | |
| switch ($hint) { | |
| case 'int': | |
| case 'integer': | |
| $error = strpos($match['given'], 'int') !== 0; | |
| break; | |
| case 'string': | |
| $error = $match['given'] != 'string'; | |
| break; | |
| case 'real': | |
| case 'float': | |
| case 'double': | |
| $error = $match['given'] != 'double'; | |
| break; | |
| case 'num': | |
| case 'number': | |
| case 'numeric': | |
| $error = strpos($match['given'], 'int') !== 0 && $match['given'] != 'double'; | |
| break; | |
| case 'bool': | |
| case 'boolean': | |
| $error = $match['given'] != 'boolean'; | |
| break; | |
| case 'object': | |
| $error = strpos($match['given'], 'instance of') !== 0; | |
| break; | |
| case 'resource': | |
| $error = $match['given'] != 'resource'; | |
| break; | |
| case 'any': | |
| case 'mixed': | |
| $error = false; | |
| break; | |
| } | |
| if ($error) { | |
| throw new \ErrorException(sprintf( | |
| 'Argument %d passed to %s must be of the type %s, %s given!', | |
| $match[1], $match[2], $hint, $match['given'] | |
| ), $ecode); | |
| } | |
| } | |
| } | |
| // don't execute php internal error handler | |
| return true; | |
| }); | |
| class User {} | |
| function get_memo() { | |
| $size = memory_get_usage(); | |
| $unit = ['b', 'kb', 'mb', 'gb', 'tb', 'pb']; | |
| return @round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) .' '. $unit[$i]; | |
| } | |
| function foo_int(int $a) {} | |
| function foo_array(array $a) {} | |
| function foo_class(User $a) {} | |
| printf("%s\n", get_memo()); | |
| for ($i = 0, $t = microtime(1); $i < 100000; $i++) { | |
| foo_int(1); | |
| } | |
| printf("%s\n", microtime(1) - $t); | |
| printf("%s\n", get_memo()); | |
| printf("----------------------\n"); | |
| printf("%s\n", get_memo()); | |
| for ($i = 0, $t = microtime(1); $i < 100000; $i++) { | |
| foo_array([]); | |
| } | |
| printf("%s\n", microtime(1) - $t); | |
| printf("%s\n", get_memo()); | |
| printf("----------------------\n"); | |
| printf("%s\n", get_memo()); | |
| for ($i = 0, $t = microtime(1); $i < 100000; $i++) { | |
| foo_class(new User); | |
| } | |
| printf("%s\n", microtime(1) - $t); | |
| printf("%s\n", get_memo()); | |
| ?> | |
| Results: | |
| 217.35 kb | |
| 1.3914940357208 | |
| 218.23 kb | |
| ---------------------- | |
| 218.23 kb | |
| 0.015022039413452 | |
| 218.23 kb | |
| ---------------------- | |
| 218.23 kb | |
| 0.029924869537354 | |
| 218.23 kb | |
| ### | |
| So, does it trigger autoloader? | |
| Absolutely NO, in my tests.. | |
| <?php | |
| spl_autoload_register(function($c) { | |
| print($c); # just print class name that tried to load | |
| }); | |
| function a(foo $f) {} | |
| a(123); # this won't but throw exception | |
| a(new foo); # this will of course | |
| ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment