Skip to content

Instantly share code, notes, and snippets.

@krmgns
Last active November 2, 2015 23:44
Show Gist options
  • Save krmgns/cd5de6397dd732751fec to your computer and use it in GitHub Desktop.
Save krmgns/cd5de6397dd732751fec to your computer and use it in GitHub Desktop.
Simulate PHP (hacked) type hint performance.
<?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